001/* 002 * BridJ - Dynamic and blazing-fast native interop for Java. 003 * http://bridj.googlecode.com/ 004 * 005 * Copyright (c) 2010-2013, Olivier Chafik (http://ochafik.com/) 006 * All rights reserved. 007 * 008 * Redistribution and use in source and binary forms, with or without 009 * modification, are permitted provided that the following conditions are met: 010 * 011 * * Redistributions of source code must retain the above copyright 012 * notice, this list of conditions and the following disclaimer. 013 * * Redistributions in binary form must reproduce the above copyright 014 * notice, this list of conditions and the following disclaimer in the 015 * documentation and/or other materials provided with the distribution. 016 * * Neither the name of Olivier Chafik nor the 017 * names of its contributors may be used to endorse or promote products 018 * derived from this software without specific prior written permission. 019 * 020 * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY 021 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 022 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 023 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY 024 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 025 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 026 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 027 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 029 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 030 */ 031package org.bridj.util; 032 033import java.lang.annotation.Annotation; 034import java.lang.reflect.AnnotatedElement; 035import java.lang.reflect.Member; 036import java.lang.reflect.Proxy; 037import org.bridj.ann.Forwardable; 038 039/** 040 * Util methods for annotations (inheritable annotations, forwarded annotations, 041 * annotations from AnnotatedElements and/or direct annotation arrays...) 042 * 043 * @author ochafik 044 */ 045public class AnnotationUtils { 046 047 public static <A extends Annotation> A getInheritableAnnotation(Class<A> ac, AnnotatedElement m, Annotation... directAnnotations) { 048 return getAnnotation(ac, true, m, directAnnotations); 049 } 050 051 public static <A extends Annotation> A getAnnotation(Class<A> ac, AnnotatedElement m, Annotation... directAnnotations) { 052 return getAnnotation(ac, false, m, directAnnotations); 053 } 054 055 private static boolean isForwardable(Class<? extends Annotation> ac) { 056 return ac.isAnnotationPresent(Forwardable.class); 057 } 058 059 public static boolean isAnnotationPresent(Class<? extends Annotation> ac, Annotation... annotations) { 060 return isAnnotationPresent(ac, isForwardable(ac), annotations); 061 } 062 063 private static boolean isAnnotationPresent(Class<? extends Annotation> ac, boolean isForwardable, Annotation... annotations) { 064 for (Annotation ann : annotations) { 065 if (ac.isInstance(ann)) { 066 return true; 067 } 068 069 if (isForwardable) { 070 if (ann.annotationType().isAnnotationPresent(ac)) { 071 return true; 072 } 073 } 074 } 075 return false; 076 } 077 078 public static boolean isAnnotationPresent(Class<? extends Annotation> ac, AnnotatedElement m, Annotation... directAnnotations) { 079 boolean isForwardable = isForwardable(ac); 080 if (m != null) { 081 if (isForwardable) { 082 if (isAnnotationPresent(ac, true, m.getAnnotations())) { 083 return true; 084 } 085 } else { 086 if (m.isAnnotationPresent(ac)) { 087 return true; 088 } 089 } 090 } 091 if (directAnnotations != null) { 092 return isAnnotationPresent(ac, isForwardable, directAnnotations); 093 } 094 095 return false; 096 } 097 098 private static <A extends Annotation> A getAnnotation(Class<A> ac, boolean inherit, AnnotatedElement m, Annotation... directAnnotations) { 099 if (directAnnotations != null) { 100 for (Annotation ann : directAnnotations) { 101 if (ac.isInstance(ann)) { 102 return ac.cast(ann); 103 } 104 } 105 } 106 107 if (m == null) { 108 return null; 109 } 110 A a = m.getAnnotation(ac); 111 if (a != null) { 112 return a; 113 } 114 115 if (inherit) { 116 if (m instanceof Member) { 117 return getAnnotation(ac, inherit, ((Member) m).getDeclaringClass()); 118 } 119 120 if (m instanceof Class<?>) { 121 Class<?> c = (Class<?>) m, dc = c.getDeclaringClass(); 122 Class p = c.getSuperclass(); 123 while (p != null) { 124 a = getAnnotation(ac, true, p); 125 if (a != null) { 126 return a; 127 } 128 p = p.getSuperclass(); 129 } 130 131 if (dc != null) { 132 return getAnnotation(ac, inherit, dc); 133 } 134 } 135 } 136 return null; 137 } 138}