Tue, 06 Mar 2012 16:09:35 -0800
7150322: Stop using drop source bundles in jaxws
Reviewed-by: darcy, ohrstrom
1 /*
2 * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
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
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
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 */
26 package com.sun.tools.internal.jxc.model.nav;
28 import com.sun.source.tree.CompilationUnitTree;
29 import com.sun.source.util.TreePath;
30 import com.sun.source.util.Trees;
31 import com.sun.xml.internal.bind.v2.model.nav.Navigator;
32 import com.sun.xml.internal.bind.v2.runtime.Location;
34 import javax.annotation.processing.ProcessingEnvironment;
35 import javax.lang.model.element.Element;
36 import javax.lang.model.element.ElementKind;
37 import javax.lang.model.element.ExecutableElement;
38 import javax.lang.model.element.Modifier;
39 import javax.lang.model.element.TypeElement;
40 import javax.lang.model.element.TypeParameterElement;
41 import javax.lang.model.element.VariableElement;
42 import javax.lang.model.type.ArrayType;
43 import javax.lang.model.type.DeclaredType;
44 import javax.lang.model.type.PrimitiveType;
45 import javax.lang.model.type.TypeKind;
46 import javax.lang.model.type.TypeMirror;
47 import javax.lang.model.type.TypeVariable;
48 import javax.lang.model.type.TypeVisitor;
49 import javax.lang.model.type.WildcardType;
50 import javax.lang.model.util.ElementFilter;
51 import javax.lang.model.util.Elements;
52 import javax.lang.model.util.SimpleTypeVisitor6;
53 import javax.lang.model.util.Types;
54 import java.util.Collection;
55 import java.util.HashMap;
56 import java.util.HashSet;
57 import java.util.List;
58 import java.util.Map;
60 /**
61 * {@link Navigator} implementation for annotation processing.
62 * TODO: check the spec on how generics are supposed to be handled
63 *
64 * @author Kohsuke Kawaguchi (kk@kohsuke.org)
65 */
66 public class ApNavigator implements Navigator<TypeMirror, TypeElement, VariableElement, ExecutableElement> {
68 private final ProcessingEnvironment env;
70 private final PrimitiveType primitiveByte;
72 public ApNavigator(ProcessingEnvironment env) {
73 this.env = env;
74 this.primitiveByte = env.getTypeUtils().getPrimitiveType(TypeKind.BYTE);
75 }
77 public TypeElement getSuperClass(TypeElement typeElement) {
78 if (typeElement.getKind().equals(ElementKind.CLASS)) {
79 TypeMirror sup = typeElement.getSuperclass();
80 if (!sup.getKind().equals(TypeKind.NONE))
81 return (TypeElement) ((DeclaredType) sup).asElement();
82 else
83 return null;
84 }
85 return env.getElementUtils().getTypeElement(Object.class.getName());
86 }
88 public TypeMirror getBaseClass(TypeMirror type, TypeElement sup) {
89 return baseClassFinder.visit(type, sup);
90 }
92 public String getClassName(TypeElement t) {
93 return t.getQualifiedName().toString();
94 }
96 public String getTypeName(TypeMirror typeMirror) {
97 return typeMirror.toString();
98 }
100 public String getClassShortName(TypeElement t) {
101 return t.getSimpleName().toString();
102 }
104 public Collection<VariableElement> getDeclaredFields(TypeElement typeElement) {
105 return ElementFilter.fieldsIn(typeElement.getEnclosedElements());
106 }
108 public VariableElement getDeclaredField(TypeElement clazz, String fieldName) {
109 for (VariableElement fd : ElementFilter.fieldsIn(clazz.getEnclosedElements())) {
110 if (fd.getSimpleName().toString().equals(fieldName))
111 return fd;
112 }
113 return null;
114 }
116 public Collection<ExecutableElement> getDeclaredMethods(TypeElement typeElement) {
117 return ElementFilter.methodsIn(typeElement.getEnclosedElements());
118 }
120 public TypeElement getDeclaringClassForField(VariableElement f) {
121 return (TypeElement) f.getEnclosingElement();
122 }
124 public TypeElement getDeclaringClassForMethod(ExecutableElement m) {
125 return (TypeElement) m.getEnclosingElement();
126 }
128 public TypeMirror getFieldType(VariableElement f) {
129 return f.asType();
130 }
132 public String getFieldName(VariableElement f) {
133 return f.getSimpleName().toString();
134 }
136 public String getMethodName(ExecutableElement m) {
137 return m.getSimpleName().toString();
138 }
140 public TypeMirror getReturnType(ExecutableElement m) {
141 return m.getReturnType();
142 }
144 public TypeMirror[] getMethodParameters(ExecutableElement m) {
145 Collection<? extends VariableElement> ps = m.getParameters();
146 TypeMirror[] r = new TypeMirror[ps.size()];
147 int i=0;
148 for (VariableElement p : ps)
149 r[i++] = p.asType();
150 return r;
151 }
153 public boolean isStaticMethod(ExecutableElement m) {
154 return hasModifier(m, Modifier.STATIC);
155 }
157 public boolean isFinalMethod(ExecutableElement m) {
158 return hasModifier(m, Modifier.FINAL);
159 }
161 private boolean hasModifier(Element d, Modifier mod) {
162 return d.getModifiers().contains(mod);
163 }
165 public boolean isSubClassOf(TypeMirror sub, TypeMirror sup) {
166 if(sup==DUMMY)
167 // see ref(). if the sub type is known to Annotation Processing,
168 // its base class must be known. Thus if the sup is DUMMY,
169 // it cannot possibly be the super type.
170 return false;
171 return env.getTypeUtils().isSubtype(sub,sup);
172 }
174 private String getSourceClassName(Class clazz) {
175 Class<?> d = clazz.getDeclaringClass();
176 if(d==null)
177 return clazz.getName();
178 else {
179 String shortName = clazz.getName().substring(d.getName().length()+1/*for $*/);
180 return getSourceClassName(d)+'.'+shortName;
181 }
182 }
184 public TypeMirror ref(Class c) {
185 if(c.isArray())
186 return env.getTypeUtils().getArrayType( ref(c.getComponentType()) );
187 if(c.isPrimitive())
188 return getPrimitive(c);
189 TypeElement t = env.getElementUtils().getTypeElement(getSourceClassName(c));
190 // Annotation Processing only operates on a set of classes used in the compilation,
191 // and it won't recognize additional classes (even if they are visible from javac)
192 // and return null.
193 //
194 // this is causing a problem where we check if a type is collection.
195 // so until the problem is fixed in Annotation Processing, work around the issue
196 // by returning a dummy token
197 // TODO: check if this is still valid
198 if(t==null)
199 return DUMMY;
200 return env.getTypeUtils().getDeclaredType(t);
201 }
203 public TypeMirror use(TypeElement t) {
204 assert t != null;
205 return env.getTypeUtils().getDeclaredType(t);
206 }
208 public TypeElement asDecl(TypeMirror m) {
209 m = env.getTypeUtils().erasure(m);
210 if (m.getKind().equals(TypeKind.DECLARED)) {
211 DeclaredType d = (DeclaredType) m;
212 return (TypeElement) d.asElement();
213 } else
214 return null;
215 }
217 public TypeElement asDecl(Class c) {
218 return env.getElementUtils().getTypeElement(getSourceClassName(c));
219 }
221 public TypeMirror erasure(TypeMirror t) {
222 Types tu = env.getTypeUtils();
223 t = tu.erasure(t);
224 if (t.getKind().equals(TypeKind.DECLARED)) {
225 DeclaredType dt = (DeclaredType)t;
226 if (!dt.getTypeArguments().isEmpty())
227 return tu.getDeclaredType((TypeElement) dt.asElement());
228 }
229 return t;
230 }
232 public boolean isAbstract(TypeElement clazz) {
233 return hasModifier(clazz,Modifier.ABSTRACT);
234 }
236 public boolean isFinal(TypeElement clazz) {
237 return hasModifier(clazz,Modifier.FINAL);
238 }
240 public VariableElement[] getEnumConstants(TypeElement clazz) {
241 List<? extends Element> elements = env.getElementUtils().getAllMembers(clazz);
242 Collection<VariableElement> constants = new HashSet<VariableElement>();
243 for (Element element : elements) {
244 if (element.getKind().equals(ElementKind.ENUM_CONSTANT)) {
245 constants.add((VariableElement) element);
246 }
247 }
248 return constants.toArray(new VariableElement[constants.size()]);
249 }
251 public TypeMirror getVoidType() {
252 return env.getTypeUtils().getNoType(TypeKind.VOID);
253 }
255 public String getPackageName(TypeElement clazz) {
256 return env.getElementUtils().getPackageOf(clazz).getQualifiedName().toString();
257 }
259 public TypeElement findClass(String className, TypeElement referencePoint) {
260 return env.getElementUtils().getTypeElement(className);
261 }
263 public boolean isBridgeMethod(ExecutableElement method) {
264 return method.getModifiers().contains(Modifier.VOLATILE);
265 }
267 public boolean isOverriding(ExecutableElement method, TypeElement base) {
268 Elements elements = env.getElementUtils();
270 while (true) {
271 for (ExecutableElement m : ElementFilter.methodsIn(elements.getAllMembers(base))) {
272 if (elements.overrides(method, m, base))
273 return true;
274 }
276 if (base.getSuperclass().getKind().equals(TypeKind.NONE))
277 return false;
278 base = (TypeElement) env.getTypeUtils().asElement(base.getSuperclass());
279 }
280 }
282 public boolean isInterface(TypeElement clazz) {
283 return clazz.getKind().isInterface();
284 }
286 public boolean isTransient(VariableElement f) {
287 return f.getModifiers().contains(Modifier.TRANSIENT);
288 }
290 public boolean isInnerClass(TypeElement clazz) {
291 return clazz.getEnclosingElement() != null && !clazz.getModifiers().contains(Modifier.STATIC);
292 }
294 @Override
295 public boolean isSameType(TypeMirror t1, TypeMirror t2) {
296 return env.getTypeUtils().isSameType(t1, t2);
297 }
299 public boolean isArray(TypeMirror type) {
300 return type != null && type.getKind().equals(TypeKind.ARRAY);
301 }
303 public boolean isArrayButNotByteArray(TypeMirror t) {
304 if(!isArray(t))
305 return false;
307 ArrayType at = (ArrayType) t;
308 TypeMirror ct = at.getComponentType();
310 return !ct.equals(primitiveByte);
311 }
313 public TypeMirror getComponentType(TypeMirror t) {
314 if (isArray(t)) {
315 ArrayType at = (ArrayType) t;
316 return at.getComponentType();
317 }
319 throw new IllegalArgumentException();
320 }
322 public TypeMirror getTypeArgument(TypeMirror typeMirror, int i) {
323 if (typeMirror != null && typeMirror.getKind().equals(TypeKind.DECLARED)) {
324 DeclaredType declaredType = (DeclaredType) typeMirror;
325 TypeMirror[] args = declaredType.getTypeArguments().toArray(new TypeMirror[declaredType.getTypeArguments().size()]);
326 return args[i];
327 } else throw new IllegalArgumentException();
328 }
330 public boolean isParameterizedType(TypeMirror typeMirror) {
331 if (typeMirror != null && typeMirror.getKind().equals(TypeKind.DECLARED)) {
332 DeclaredType d = (DeclaredType) typeMirror;
333 return !d.getTypeArguments().isEmpty();
334 }
335 return false;
336 }
338 public boolean isPrimitive(TypeMirror t) {
339 return t.getKind().isPrimitive();
340 }
342 private static final Map<Class, TypeKind> primitives = new HashMap<Class, TypeKind>();
344 static {
345 primitives.put(Integer.TYPE, TypeKind.INT);
346 primitives.put(Byte.TYPE, TypeKind.BYTE);
347 primitives.put(Float.TYPE, TypeKind.FLOAT);
348 primitives.put(Boolean.TYPE, TypeKind.BOOLEAN);
349 primitives.put(Short.TYPE, TypeKind.SHORT);
350 primitives.put(Long.TYPE, TypeKind.LONG);
351 primitives.put(Double.TYPE, TypeKind.DOUBLE);
352 primitives.put(Character.TYPE, TypeKind.CHAR);
353 }
355 public TypeMirror getPrimitive(Class primitiveType) {
356 assert primitiveType.isPrimitive();
357 if(primitiveType==void.class)
358 return getVoidType();
359 return env.getTypeUtils().getPrimitiveType(primitives.get(primitiveType));
360 }
362 /**
363 * see {@link #ref(Class)}.
364 */
365 private static final TypeMirror DUMMY = new TypeMirror() {
366 @Override
367 public <R, P> R accept(TypeVisitor<R, P> v, P p) {
368 throw new IllegalStateException();
369 }
371 @Override
372 public TypeKind getKind() {
373 throw new IllegalStateException();
374 }
375 };
377 public Location getClassLocation(TypeElement typeElement) {
378 Trees trees = Trees.instance(env);
379 return getLocation(typeElement.getQualifiedName().toString(), trees.getPath(typeElement));
380 }
382 public Location getFieldLocation(VariableElement variableElement) {
383 return getLocation(variableElement);
384 }
386 public Location getMethodLocation(ExecutableElement executableElement) {
387 return getLocation(executableElement);
388 }
390 public boolean hasDefaultConstructor(TypeElement t) {
391 if (t == null || !t.getKind().equals(ElementKind.CLASS))
392 return false;
394 for (ExecutableElement init : ElementFilter.constructorsIn(env.getElementUtils().getAllMembers(t))) {
395 if (init.getParameters().isEmpty())
396 return true;
397 }
398 return false;
399 }
401 public boolean isStaticField(VariableElement f) {
402 return hasModifier(f,Modifier.STATIC);
403 }
405 public boolean isPublicMethod(ExecutableElement m) {
406 return hasModifier(m,Modifier.PUBLIC);
407 }
409 public boolean isPublicField(VariableElement f) {
410 return hasModifier(f,Modifier.PUBLIC);
411 }
413 public boolean isEnum(TypeElement t) {
414 return t != null && t.getKind().equals(ElementKind.ENUM);
415 }
417 private Location getLocation(Element element) {
418 Trees trees = Trees.instance(env);
419 return getLocation(
420 ((TypeElement) element.getEnclosingElement()).getQualifiedName() + "." + element.getSimpleName(),
421 trees.getPath(element)
422 );
423 }
425 private Location getLocation(final String name, final TreePath treePath) {
426 return new Location() {
427 public String toString() {
428 if (treePath == null)
429 return name + " (Unknown Source)";
430 // just like stack trace, we just print the file name and
431 // not the whole path. The idea is that the package name should
432 // provide enough clue on which directory it lives.
433 CompilationUnitTree compilationUnit = treePath.getCompilationUnit();
434 Trees trees = Trees.instance(env);
435 long startPosition = trees.getSourcePositions().getStartPosition(compilationUnit, treePath.getLeaf());
436 return name + "(" +
437 compilationUnit.getSourceFile().getName() + ":" + compilationUnit.getLineMap().getLineNumber(startPosition) +
438 ")";
439 }
440 };
441 }
443 /**
444 * Implements {@link #getBaseClass}.
445 */
446 private final SimpleTypeVisitor6<TypeMirror, TypeElement> baseClassFinder = new SimpleTypeVisitor6<TypeMirror, TypeElement>() {
447 @Override
448 public TypeMirror visitDeclared(DeclaredType t, TypeElement sup) {
449 if (t.asElement().equals(sup))
450 return t;
452 for (TypeMirror i : env.getTypeUtils().directSupertypes(t)) {
453 TypeMirror r = visitDeclared((DeclaredType) i, sup);
454 if (r != null)
455 return r;
456 }
458 // otherwise recursively apply super class and base types
459 TypeMirror superclass = ((TypeElement) t.asElement()).getSuperclass();
460 if (!superclass.getKind().equals(TypeKind.NONE)) {
461 TypeMirror r = visitDeclared((DeclaredType) superclass, sup);
462 if (r != null)
463 return r;
464 }
465 return null;
466 }
468 @Override
469 public TypeMirror visitTypeVariable(TypeVariable t, TypeElement typeElement) {
470 // we are checking if T (declared as T extends A&B&C) is assignable to sup.
471 // so apply bounds recursively.
472 for (TypeMirror typeMirror : ((TypeParameterElement) t.asElement()).getBounds()) {
473 TypeMirror m = visit(typeMirror, typeElement);
474 if (m != null)
475 return m;
476 }
477 return null;
478 }
480 @Override
481 public TypeMirror visitArray(ArrayType t, TypeElement typeElement) {
482 // we are checking if t=T[] is assignable to sup.
483 // the only case this is allowed is sup=Object,
484 // and Object isn't parameterized.
485 return null;
486 }
488 @Override
489 public TypeMirror visitWildcard(WildcardType t, TypeElement typeElement) {
490 // we are checking if T (= ? extends A&B&C) is assignable to sup.
491 // so apply bounds recursively.
492 return visit(t.getExtendsBound(), typeElement);
493 }
495 @Override
496 protected TypeMirror defaultAction(TypeMirror e, TypeElement typeElement) {
497 return e;
498 }
499 };
500 }