17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.reflect.annotation;
27
28 import java.lang.annotation.*;
29 import java.lang.reflect.*;
30 import java.security.AccessController;
31 import java.security.PrivilegedAction;
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.Objects;
37
38 import jdk.internal.misc.SharedSecrets;
39 import jdk.internal.misc.JavaLangAccess;
40 import jdk.internal.reflect.ReflectionFactory;
41
42 public final class AnnotationSupport {
43 private static final JavaLangAccess LANG_ACCESS = SharedSecrets.getJavaLangAccess();
44
45 /**
46 * Finds and returns all annotations in {@code annotations} matching
47 * the given {@code annoClass}.
48 *
49 * Apart from annotations directly present in {@code annotations} this
50 * method searches for annotations inside containers i.e. indirectly
51 * present annotations.
52 *
53 * The order of the elements in the array returned depends on the iteration
54 * order of the provided map. Specifically, the directly present annotations
55 * come before the indirectly present annotations if and only if the
56 * directly present annotations come before the indirectly present
160 Map<Class<? extends Annotation>, Annotation> declaredAnnotations,
161 Class<?> decl,
162 Class<A> annoClass) {
163 Objects.requireNonNull(decl);
164
165 // Search declared
166 A[] result = getDirectlyAndIndirectlyPresent(declaredAnnotations, annoClass);
167
168 // Search inherited
169 if(AnnotationType.getInstance(annoClass).isInherited()) {
170 Class<?> superDecl = decl.getSuperclass();
171 while (result.length == 0 && superDecl != null) {
172 result = getDirectlyAndIndirectlyPresent(LANG_ACCESS.getDeclaredAnnotationMap(superDecl), annoClass);
173 superDecl = superDecl.getSuperclass();
174 }
175 }
176
177 return result;
178 }
179
180
181 /* Reflectively invoke the values-method of the given annotation
182 * (container), cast it to an array of annotations and return the result.
183 */
184 private static <A extends Annotation> A[] getValueArray(Annotation container) {
185 try {
186 // According to JLS the container must have an array-valued value
187 // method. Get the AnnotationType, get the "value" method and invoke
188 // it to get the content.
189
190 Class<? extends Annotation> containerClass = container.annotationType();
191 AnnotationType annoType = AnnotationType.getInstance(containerClass);
192 if (annoType == null)
193 throw invalidContainerException(container, null);
194 Method m = annoType.members().get("value");
195 if (m == null)
196 throw invalidContainerException(container, null);
197
198 if (Proxy.isProxyClass(container.getClass())) {
199 // Invoke by invocation handler
|
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.reflect.annotation;
27
28 import java.lang.annotation.*;
29 import java.lang.reflect.*;
30 import java.security.AccessController;
31 import java.security.PrivilegedAction;
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.Objects;
37 import java.util.function.IntFunction;
38
39 import jdk.internal.misc.SharedSecrets;
40 import jdk.internal.misc.JavaLangAccess;
41 import jdk.internal.reflect.ReflectionFactory;
42
43 public final class AnnotationSupport {
44 private static final JavaLangAccess LANG_ACCESS = SharedSecrets.getJavaLangAccess();
45
46 /**
47 * Finds and returns all annotations in {@code annotations} matching
48 * the given {@code annoClass}.
49 *
50 * Apart from annotations directly present in {@code annotations} this
51 * method searches for annotations inside containers i.e. indirectly
52 * present annotations.
53 *
54 * The order of the elements in the array returned depends on the iteration
55 * order of the provided map. Specifically, the directly present annotations
56 * come before the indirectly present annotations if and only if the
57 * directly present annotations come before the indirectly present
161 Map<Class<? extends Annotation>, Annotation> declaredAnnotations,
162 Class<?> decl,
163 Class<A> annoClass) {
164 Objects.requireNonNull(decl);
165
166 // Search declared
167 A[] result = getDirectlyAndIndirectlyPresent(declaredAnnotations, annoClass);
168
169 // Search inherited
170 if(AnnotationType.getInstance(annoClass).isInherited()) {
171 Class<?> superDecl = decl.getSuperclass();
172 while (result.length == 0 && superDecl != null) {
173 result = getDirectlyAndIndirectlyPresent(LANG_ACCESS.getDeclaredAnnotationMap(superDecl), annoClass);
174 superDecl = superDecl.getSuperclass();
175 }
176 }
177
178 return result;
179 }
180
181
182 /**
183 * There are cases where the number of parameters present for a constructor
184 * in source code and the number of parameters present for that constructor
185 * in the class file differ. Constructors of enum classes, anonymous classes,
186 * local classes and member classes may have additional parameters generated
187 * by compiler. This method fixes an array of "annotations collections"
188 * by prefixing and/or suffixing it with "empty collection" elements
189 * for parameters added by compiler.
190 *
191 * @param constructor the constructor
192 * @param annColls an array of annotation collections for parameters in source code
193 * @param emptyColl an empty collection replicated for compiler generated parameters
194 * @param arrayFactory a factory for arrays of collections
195 * @param <A> the type of annotation collection
196 * @return new array of annotation collections for parameters in class file
197 */
198 public static <A> A[] fixConstructorParameterAnnotations(
199 Constructor<?> constructor, A[] annColls, A emptyColl, IntFunction<A[]> arrayFactory)
200 {
201 int prefixLength = 0;
202 boolean mayHaveSuffix = false;
203 Class<?> declaringClass = constructor.getDeclaringClass();
204 if (declaringClass.isEnum() ||
205 (declaringClass.isAnonymousClass() && declaringClass.getSuperclass().isEnum())) {
206 // enum class or enum constant anonymous subclass
207 prefixLength = 2;
208 mayHaveSuffix = true;
209 } else if (declaringClass.isLocalClass() || declaringClass.isAnonymousClass()) {
210 // local or anonymous class
211 if (!Modifier.isStatic(declaringClass.getModifiers())) {
212 prefixLength = 1;
213 }
214 mayHaveSuffix = true;
215 } else if (declaringClass.isMemberClass()) {
216 // member class
217 if (!Modifier.isStatic(declaringClass.getModifiers())) {
218 prefixLength = 1;
219 }
220 }
221 // compute total length of array of arrays
222 int len = annColls.length + prefixLength;
223 if (len < constructor.getParameterCount() && mayHaveSuffix) {
224 len = constructor.getParameterCount();
225 }
226 // prepend empty annotations prefix and/or append suffix if needed
227 if (len > annColls.length) {
228 A[] newAnnColls = arrayFactory.apply(len);
229 Arrays.fill(newAnnColls, 0, prefixLength, emptyColl);
230 System.arraycopy(annColls, 0,
231 newAnnColls, prefixLength,
232 annColls.length);
233 Arrays.fill(newAnnColls,
234 prefixLength + annColls.length, newAnnColls.length,
235 emptyColl);
236 annColls = newAnnColls;
237 }
238 return annColls;
239 }
240
241 /* Reflectively invoke the values-method of the given annotation
242 * (container), cast it to an array of annotations and return the result.
243 */
244 private static <A extends Annotation> A[] getValueArray(Annotation container) {
245 try {
246 // According to JLS the container must have an array-valued value
247 // method. Get the AnnotationType, get the "value" method and invoke
248 // it to get the content.
249
250 Class<? extends Annotation> containerClass = container.annotationType();
251 AnnotationType annoType = AnnotationType.getInstance(containerClass);
252 if (annoType == null)
253 throw invalidContainerException(container, null);
254 Method m = annoType.members().get("value");
255 if (m == null)
256 throw invalidContainerException(container, null);
257
258 if (Proxy.isProxyClass(container.getClass())) {
259 // Invoke by invocation handler
|