src/share/classes/com/sun/tools/javac/model/JavacElements.java

changeset 1491
9f42a06a49c0
parent 1374
c002fdee76fd
child 1492
df694c775e8a
equal deleted inserted replaced
1490:fc4cb1577ad6 1491:9f42a06a49c0
1 /* 1 /*
2 * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this 7 * published by the Free Software Foundation. Oracle designates this
25 25
26 package com.sun.tools.javac.model; 26 package com.sun.tools.javac.model;
27 27
28 import java.lang.annotation.Annotation; 28 import java.lang.annotation.Annotation;
29 import java.lang.annotation.Inherited; 29 import java.lang.annotation.Inherited;
30 import java.lang.reflect.InvocationTargetException;
31 import java.lang.reflect.Method;
30 import java.util.Map; 32 import java.util.Map;
31 33
32 import javax.lang.model.SourceVersion; 34 import javax.lang.model.SourceVersion;
33 import javax.lang.model.element.*; 35 import javax.lang.model.element.*;
34 import javax.lang.model.type.DeclaredType; 36 import javax.lang.model.type.DeclaredType;
94 names = Names.instance(context); 96 names = Names.instance(context);
95 types = Types.instance(context); 97 types = Types.instance(context);
96 enter = Enter.instance(context); 98 enter = Enter.instance(context);
97 } 99 }
98 100
99 101 /**
100 /** 102 * An internal-use utility that creates a runtime view of an
101 * An internal-use utility that creates a reified annotation. 103 * annotation. This is the implementation of
104 * Element.getAnnotation(Class).
102 */ 105 */
103 public static <A extends Annotation> A getAnnotation(Symbol annotated, 106 public static <A extends Annotation> A getAnnotation(Symbol annotated,
104 Class<A> annoType) { 107 Class<A> annoType) {
105 if (!annoType.isAnnotation()) 108 if (!annoType.isAnnotation())
106 throw new IllegalArgumentException("Not an annotation type: " 109 throw new IllegalArgumentException("Not an annotation type: "
107 + annoType); 110 + annoType);
111 Attribute.Compound c;
112 if (annotated.kind == Kinds.TYP && annotated instanceof ClassSymbol) {
113 c = getAttributeOnClass((ClassSymbol)annotated, annoType);
114 } else {
115 c = getAttribute(annotated, annoType);
116 }
117 return c == null ? null : AnnotationProxyMaker.generateAnnotation(c, annoType);
118 }
119
120 // Helper to getAnnotation[s]
121 private static <A extends Annotation> Attribute.Compound getAttribute(Symbol annotated,
122 Class<A> annoType) {
108 String name = annoType.getName(); 123 String name = annoType.getName();
109 for (Attribute.Compound anno : annotated.getAnnotationMirrors()) 124
125 for (Attribute.Compound anno : annotated.getRawAttributes())
110 if (name.equals(anno.type.tsym.flatName().toString())) 126 if (name.equals(anno.type.tsym.flatName().toString()))
111 return AnnotationProxyMaker.generateAnnotation(anno, annoType); 127 return anno;
128
112 return null; 129 return null;
113 } 130 }
114 131 // Helper to getAnnotation[s]
115 /** 132 private static <A extends Annotation> Attribute.Compound getAttributeOnClass(ClassSymbol annotated,
116 * An internal-use utility that creates a reified annotation. 133 Class<A> annoType) {
117 * This overloaded version take annotation inheritance into account.
118 */
119 public static <A extends Annotation> A getAnnotation(ClassSymbol annotated,
120 Class<A> annoType) {
121 boolean inherited = annoType.isAnnotationPresent(Inherited.class); 134 boolean inherited = annoType.isAnnotationPresent(Inherited.class);
122 A result = null; 135 Attribute.Compound result = null;
123 while (annotated.name != annotated.name.table.names.java_lang_Object) { 136 while (annotated.name != annotated.name.table.names.java_lang_Object) {
124 result = getAnnotation((Symbol)annotated, annoType); 137 result = getAttribute(annotated, annoType);
125 if (result != null || !inherited) 138 if (result != null || !inherited)
126 break; 139 break;
127 Type sup = annotated.getSuperclass(); 140 Type sup = annotated.getSuperclass();
128 if (!sup.hasTag(CLASS) || sup.isErroneous()) 141 if (!sup.hasTag(CLASS) || sup.isErroneous())
129 break; 142 break;
130 annotated = (ClassSymbol) sup.tsym; 143 annotated = (ClassSymbol) sup.tsym;
131 } 144 }
132 return result; 145 return result;
133 } 146 }
134 147
148 /**
149 * An internal-use utility that creates a runtime view of
150 * annotations. This is the implementation of
151 * Element.getAnnotations(Class).
152 */
153 public static <A extends Annotation> A[] getAnnotations(Symbol annotated,
154 Class<A> annoType) {
155 if (!annoType.isAnnotation())
156 throw new IllegalArgumentException("Not an annotation type: "
157 + annoType);
158 // If annoType does not declare a container this is equivalent to wrapping
159 // getAnnotation(...) in an array.
160 Class <? extends Annotation> containerType = getContainer(annoType);
161 if (containerType == null) {
162 A res = getAnnotation(annotated, annoType);
163 int size;
164 if (res == null) {
165 size = 0;
166 } else {
167 size = 1;
168 }
169 @SuppressWarnings("unchecked") // annoType is the Class for A
170 A[] arr = (A[])java.lang.reflect.Array.newInstance(annoType, size);
171 if (res != null)
172 arr[0] = res;
173 return arr;
174 }
175
176 // So we have a containing type
177 String name = annoType.getName();
178 String annoTypeName = annoType.getSimpleName();
179 String containerTypeName = containerType.getSimpleName();
180 int directIndex = -1, containerIndex = -1;
181 Attribute.Compound direct = null, container = null;
182 Attribute.Compound[] rawAttributes = annotated.getRawAttributes().toArray(new Attribute.Compound[0]);
183
184 // Find directly present annotations
185 for (int i = 0; i < rawAttributes.length; i++) {
186 if (annoTypeName.equals(rawAttributes[i].type.tsym.flatName().toString())) {
187 directIndex = i;
188 direct = rawAttributes[i];
189 } else if(containerTypeName != null &&
190 containerTypeName.equals(rawAttributes[i].type.tsym.flatName().toString())) {
191 containerIndex = i;
192 container = rawAttributes[i];
193 }
194 }
195 // Deal with inherited annotations
196 if (annotated.kind == Kinds.TYP &&
197 (annotated instanceof ClassSymbol)) {
198 ClassSymbol s = (ClassSymbol)annotated;
199 if (direct == null && container == null) {
200 direct = getAttributeOnClass(s, annoType);
201 container = getAttributeOnClass(s, containerType);
202
203 // both are inherited and found, put container last
204 if (direct != null && container != null) {
205 directIndex = 0;
206 containerIndex = 1;
207 } else if (direct != null) {
208 directIndex = 0;
209 } else {
210 containerIndex = 0;
211 }
212 } else if (direct == null) {
213 direct = getAttributeOnClass(s, annoType);
214 if (direct != null)
215 directIndex = containerIndex + 1;
216 } else if (container == null) {
217 container = getAttributeOnClass(s, containerType);
218 if (container != null)
219 containerIndex = directIndex + 1;
220 }
221 }
222
223 // Pack them in an array
224 Attribute[] contained0 = new Attribute[0];
225 if (container != null)
226 contained0 = unpackAttributes(container);
227 ListBuffer<Attribute.Compound> compounds = ListBuffer.lb();
228 for (Attribute a : contained0)
229 if (a instanceof Attribute.Compound)
230 compounds = compounds.append((Attribute.Compound)a);
231 Attribute.Compound[] contained = compounds.toArray(new Attribute.Compound[0]);
232
233 int size = (direct == null ? 0 : 1) + contained.length;
234 @SuppressWarnings("unchecked") // annoType is the Class for A
235 A[] arr = (A[])java.lang.reflect.Array.newInstance(annoType, size);
236
237 // if direct && container, which is first?
238 int insert = -1;
239 int length = arr.length;
240 if (directIndex >= 0 && containerIndex >= 0) {
241 if (directIndex < containerIndex) {
242 arr[0] = AnnotationProxyMaker.generateAnnotation(direct, annoType);
243 insert = 1;
244 } else {
245 arr[arr.length - 1] = AnnotationProxyMaker.generateAnnotation(direct, annoType);
246 insert = 0;
247 length--;
248 }
249 } else if (directIndex >= 0) {
250 arr[0] = AnnotationProxyMaker.generateAnnotation(direct, annoType);
251 return arr;
252 } else {
253 // Only container
254 insert = 0;
255 }
256
257 for (int i = 0; i + insert < length; i++)
258 arr[insert + i] = AnnotationProxyMaker.generateAnnotation(contained[i], annoType);
259
260 return arr;
261 }
262
263 // Needed to unpack the runtime view of containing annotations
264 private static final Class<? extends Annotation> CONTAINED_BY_CLASS = initContainedBy();
265 private static final Method VALUE_ELEMENT_METHOD = initValueElementMethod();
266
267 private static Class<? extends Annotation> initContainedBy() {
268 try {
269 @SuppressWarnings("unchecked") // java.lang.annotation.ContainedBy extends Annotation by being an annotation type
270 Class<? extends Annotation> c = (Class)Class.forName("java.lang.annotation.ContainedBy");
271 return c;
272 } catch (ClassNotFoundException e) {
273 return null;
274 } catch (SecurityException e) {
275 return null;
276 }
277 }
278 private static Method initValueElementMethod() {
279 if (CONTAINED_BY_CLASS == null)
280 return null;
281
282 Method m = null;
283 try {
284 m = CONTAINED_BY_CLASS.getMethod("value");
285 if (m != null)
286 m.setAccessible(true);
287 return m;
288 } catch (NoSuchMethodException e) {
289 return null;
290 }
291 }
292
293 // Helper to getAnnotations
294 private static Class<? extends Annotation> getContainer(Class<? extends Annotation> annoType) {
295 // Since we can not refer to java.lang.annotation.ContainedBy until we are
296 // bootstrapping with java 8 we need to get the ContainedBy annotation using
297 // reflective invocations instead of just using its type and element method.
298 if (CONTAINED_BY_CLASS != null &&
299 VALUE_ELEMENT_METHOD != null) {
300 // Get the ContainedBy instance on the annotations declaration
301 Annotation containedBy = (Annotation)annoType.getAnnotation(CONTAINED_BY_CLASS);
302 if (containedBy != null) {
303 try {
304 // Get the value element, it should be a class
305 // indicating the containing annotation type
306 @SuppressWarnings("unchecked")
307 Class<? extends Annotation> containerType = (Class)VALUE_ELEMENT_METHOD.invoke(containedBy);
308 if (containerType == null)
309 return null;
310
311 return containerType;
312 } catch (ClassCastException e) {
313 return null;
314 } catch (IllegalAccessException e) {
315 return null;
316 } catch (InvocationTargetException e ) {
317 return null;
318 }
319 }
320 }
321 return null;
322 }
323 // Helper to getAnnotations
324 private static Attribute[] unpackAttributes(Attribute.Compound container) {
325 // We now have an instance of the container,
326 // unpack it returning an instance of the
327 // contained type or null
328 return ((Attribute.Array)container.member(container.type.tsym.name.table.names.value)).values;
329 }
135 330
136 public PackageSymbol getPackageElement(CharSequence name) { 331 public PackageSymbol getPackageElement(CharSequence name) {
137 String strName = name.toString(); 332 String strName = name.toString();
138 if (strName.equals("")) 333 if (strName.equals(""))
139 return syms.unnamedPackage; 334 return syms.unnamedPackage;
236 } 431 }
237 Vis vis = new Vis(); 432 Vis vis = new Vis();
238 tree.accept(vis); 433 tree.accept(vis);
239 if (vis.result == null) 434 if (vis.result == null)
240 return null; 435 return null;
436
437 List<Attribute.Compound> annos = sym.getRawAttributes();
241 return matchAnnoToTree(cast(Attribute.Compound.class, findme), 438 return matchAnnoToTree(cast(Attribute.Compound.class, findme),
242 sym.getAnnotationMirrors(), 439 annos,
243 vis.result); 440 vis.result);
244 } 441 }
245 442
246 /** 443 /**
247 * Returns the tree for an annotation given a list of annotations 444 * Returns the tree for an annotation given a list of annotations
440 * @param e the element being examined 637 * @param e the element being examined
441 * @return all annotations of the element 638 * @return all annotations of the element
442 */ 639 */
443 public List<Attribute.Compound> getAllAnnotationMirrors(Element e) { 640 public List<Attribute.Compound> getAllAnnotationMirrors(Element e) {
444 Symbol sym = cast(Symbol.class, e); 641 Symbol sym = cast(Symbol.class, e);
445 List<Attribute.Compound> annos = sym.getAnnotationMirrors(); 642 List<Attribute.Compound> annos = sym.getRawAttributes();
446 while (sym.getKind() == ElementKind.CLASS) { 643 while (sym.getKind() == ElementKind.CLASS) {
447 Type sup = ((ClassSymbol) sym).getSuperclass(); 644 Type sup = ((ClassSymbol) sym).getSuperclass();
448 if (!sup.hasTag(CLASS) || sup.isErroneous() || 645 if (!sup.hasTag(CLASS) || sup.isErroneous() ||
449 sup.tsym == syms.objectType.tsym) { 646 sup.tsym == syms.objectType.tsym) {
450 break; 647 break;
451 } 648 }
452 sym = sup.tsym; 649 sym = sup.tsym;
453 List<Attribute.Compound> oldAnnos = annos; 650 List<Attribute.Compound> oldAnnos = annos;
454 for (Attribute.Compound anno : sym.getAnnotationMirrors()) { 651 List<Attribute.Compound> newAnnos = sym.getRawAttributes();
652 for (Attribute.Compound anno : newAnnos) {
455 if (isInherited(anno.type) && 653 if (isInherited(anno.type) &&
456 !containsAnnoOfType(oldAnnos, anno.type)) { 654 !containsAnnoOfType(oldAnnos, anno.type)) {
457 annos = annos.prepend(anno); 655 annos = annos.prepend(anno);
458 } 656 }
459 } 657 }
463 661
464 /** 662 /**
465 * Tests whether an annotation type is @Inherited. 663 * Tests whether an annotation type is @Inherited.
466 */ 664 */
467 private boolean isInherited(Type annotype) { 665 private boolean isInherited(Type annotype) {
468 for (Attribute.Compound anno : annotype.tsym.getAnnotationMirrors()) { 666 return annotype.tsym.attribute(syms.inheritedType.tsym) != null;
469 if (anno.type.tsym == syms.inheritedType.tsym)
470 return true;
471 }
472 return false;
473 } 667 }
474 668
475 /** 669 /**
476 * Tests whether a list of annotations contains an annotation 670 * Tests whether a list of annotations contains an annotation
477 * of a given type. 671 * of a given type.

mercurial