1
10
11 package com.sun.xml.bind.v2.model.nav;
12
13 import java.lang.reflect.Array;
14 import java.lang.reflect.Field;
15 import java.lang.reflect.GenericArrayType;
16 import java.lang.reflect.GenericDeclaration;
17 import java.lang.reflect.Method;
18 import java.lang.reflect.Modifier;
19 import java.lang.reflect.ParameterizedType;
20 import java.lang.reflect.Type;
21 import java.lang.reflect.TypeVariable;
22 import java.lang.reflect.WildcardType;
23 import java.security.AccessController;
24 import java.security.PrivilegedAction;
25 import java.util.Arrays;
26 import java.util.Collection;
27
28 import com.sun.xml.bind.v2.runtime.Location;
29
30
34 final class ReflectionNavigator implements Navigator<Type, Class, Field, Method> {
35
36
37 private static final ReflectionNavigator INSTANCE = new ReflectionNavigator();
38
39 static ReflectionNavigator getInstance() {
40 return INSTANCE;
41 }
42
43 private ReflectionNavigator() {
44 }
45
46
47 public Class getSuperClass(Class clazz) {
48 if (clazz == Object.class) {
49 return null;
50 }
51 Class sc = clazz.getSuperclass();
52 if (sc == null) {
53 sc = Object.class;
54 }
55 return sc;
56 }
57
58 private static final TypeVisitor<Type, Class> baseClassFinder = new TypeVisitor<Type, Class>() {
59
60 public Type onClass(Class c, Class sup) {
61
62 if (sup == c) {
63 return sup;
64 }
65
66 Type r;
67
68 Type sc = c.getGenericSuperclass();
69 if (sc != null) {
70 r = visit(sc, sup);
71 if (r != null) {
72 return r;
73 }
74 }
75
76 for (Type i : c.getGenericInterfaces()) {
77 r = visit(i, sup);
78 if (r != null) {
79 return r;
80 }
81 }
82
83 return null;
84 }
85
86 public Type onParameterizdType(ParameterizedType p, Class sup) {
87 Class raw = (Class) p.getRawType();
88 if (raw == sup) {
89
90 return p;
91 } else {
92
93 Type r = raw.getGenericSuperclass();
94 if (r != null) {
95 r = visit(bind(r, raw, p), sup);
96 }
97 if (r != null) {
98 return r;
99 }
100 for (Type i : raw.getGenericInterfaces()) {
101 r = visit(bind(i, raw, p), sup);
102 if (r != null) {
103 return r;
104 }
105 }
106 return null;
107 }
108 }
109
110 public Type onGenericArray(GenericArrayType g, Class sup) {
111
112 return null;
113 }
114
115 public Type onVariable(TypeVariable v, Class sup) {
116 return visit(v.getBounds()[0], sup);
117 }
118
119 public Type onWildcard(WildcardType w, Class sup) {
120
121 return null;
122 }
123
124
132 private Type bind(Type t, GenericDeclaration decl, ParameterizedType args) {
133 return binder.visit(t, new BinderArg(decl, args.getActualTypeArguments()));
134 }
135 };
136
137 private static class BinderArg {
138
139 final TypeVariable[] params;
140 final Type[] args;
141
142 BinderArg(TypeVariable[] params, Type[] args) {
143 this.params = params;
144 this.args = args;
145 assert params.length == args.length;
146 }
147
148 public BinderArg(GenericDeclaration decl, Type[] args) {
149 this(decl.getTypeParameters(), args);
150 }
151
152 Type replace(TypeVariable v) {
153 for (int i = 0; i < params.length; i++) {
154 if (params[i].equals(v)) {
155 return args[i];
156 }
157 }
158 return v;
159 }
160 }
161 private static final TypeVisitor<Type, BinderArg> binder = new TypeVisitor<Type, BinderArg>() {
162
163 public Type onClass(Class c, BinderArg args) {
164 return c;
165 }
166
167 public Type onParameterizdType(ParameterizedType p, BinderArg args) {
168 Type[] params = p.getActualTypeArguments();
169
170 boolean different = false;
171 for (int i = 0; i < params.length; i++) {
172 Type t = params[i];
173 params[i] = visit(t, args);
174 different |= t != params[i];
175 }
176
177 Type newOwner = p.getOwnerType();
178 if (newOwner != null) {
179 newOwner = visit(newOwner, args);
180 }
181 different |= p.getOwnerType() != newOwner;
182
183 if (!different) {
184 return p;
185 }
186
187 return new ParameterizedTypeImpl((Class<?>) p.getRawType(), params, newOwner);
188 }
189
190 public Type onGenericArray(GenericArrayType g, BinderArg types) {
191 Type c = visit(g.getGenericComponentType(), types);
192 if (c == g.getGenericComponentType()) {
193 return g;
194 }
195
196 return new GenericArrayTypeImpl(c);
197 }
198
199 public Type onVariable(TypeVariable v, BinderArg types) {
200 return types.replace(v);
201 }
202
203 public Type onWildcard(WildcardType w, BinderArg types) {
204
205
206
207 Type[] lb = w.getLowerBounds();
208 Type[] ub = w.getUpperBounds();
209 boolean diff = false;
210
211 for (int i = 0; i < lb.length; i++) {
212 Type t = lb[i];
213 lb[i] = visit(t, types);
214 diff |= (t != lb[i]);
215 }
216
217 for (int i = 0; i < ub.length; i++) {
218 Type t = ub[i];
219 ub[i] = visit(t, types);
220 diff |= (t != ub[i]);
221 }
222
223 if (!diff) {
224 return w;
225 }
226
227 return new WildcardTypeImpl(lb, ub);
228 }
229 };
230
231 public Type getBaseClass(Type t, Class sup) {
232 return baseClassFinder.visit(t, sup);
233 }
234
235 public String getClassName(Class clazz) {
236 return clazz.getName();
237 }
238
239 public String getTypeName(Type type) {
240 if (type instanceof Class) {
241 Class c = (Class) type;
242 if (c.isArray()) {
243 return getTypeName(c.getComponentType()) + "[]";
244 }
245 return c.getName();
246 }
247 return type.toString();
248 }
249
250 public String getClassShortName(Class clazz) {
251 return clazz.getSimpleName();
252 }
253
254 public Collection<? extends Field> getDeclaredFields(final Class clazz) {
255 Field[] fields = AccessController.doPrivileged(new PrivilegedAction<Field[]>() {
256 @Override
257 public Field[] run() {
258 return clazz.getDeclaredFields();
259 }
260 });
261 return Arrays.asList(fields);
262 }
263
264 public Field getDeclaredField(final Class clazz, final String fieldName) {
265 return AccessController.doPrivileged(new PrivilegedAction<Field>() {
266 @Override
267 public Field run() {
268 try {
269 return clazz.getDeclaredField(fieldName);
270 } catch (NoSuchFieldException e) {
271 return null;
272 }
273 }
274 });
275 }
276
277 public Collection<? extends Method> getDeclaredMethods(final Class clazz) {
278 Method[] methods =
279 AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
280 @Override
281 public Method[] run() {
282 return clazz.getDeclaredMethods();
283 }
284 });
285 return Arrays.asList(methods);
286 }
287
288 public Class getDeclaringClassForField(Field field) {
289 return field.getDeclaringClass();
290 }
291
292 public Class getDeclaringClassForMethod(Method method) {
293 return method.getDeclaringClass();
294 }
295
296 public Type getFieldType(Field field) {
297 if (field.getType().isArray()) {
298 Class c = field.getType().getComponentType();
299 if (c.isPrimitive()) {
300 return Array.newInstance(c, 0).getClass();
301 }
302 }
303 return fix(field.getGenericType());
304 }
305
306 public String getFieldName(Field field) {
307 return field.getName();
308 }
309
310 public String getMethodName(Method method) {
311 return method.getName();
312 }
313
314 public Type getReturnType(Method method) {
315 return fix(method.getGenericReturnType());
316 }
317
318 public Type[] getMethodParameters(Method method) {
319 return method.getGenericParameterTypes();
320 }
321
322 public boolean isStaticMethod(Method method) {
323 return Modifier.isStatic(method.getModifiers());
324 }
325
326 public boolean isFinalMethod(Method method) {
327 return Modifier.isFinal(method.getModifiers());
328 }
329
330 public boolean isSubClassOf(Type sub, Type sup) {
331 return erasure(sup).isAssignableFrom(erasure(sub));
332 }
333
334 public Class ref(Class c) {
335 return c;
336 }
337
338 public Class use(Class c) {
339 return c;
340 }
341
342 public Class asDecl(Type t) {
343 return erasure(t);
344 }
345
346 public Class asDecl(Class c) {
347 return c;
348 }
349
352 private static final TypeVisitor<Class, Void> eraser = new TypeVisitor<Class, Void>() {
353
354 public Class onClass(Class c, Void v) {
355 return c;
356 }
357
358 public Class onParameterizdType(ParameterizedType p, Void v) {
359
360 return visit(p.getRawType(), null);
361 }
362
363 public Class onGenericArray(GenericArrayType g, Void v) {
364 return Array.newInstance(
365 visit(g.getGenericComponentType(), null),
366 0).getClass();
367 }
368
369 public Class onVariable(TypeVariable tv, Void v) {
370 return visit(tv.getBounds()[0], null);
371 }
372
373 public Class onWildcard(WildcardType w, Void v) {
374 return visit(w.getUpperBounds()[0], null);
375 }
376 };
377
378
393 public <T> Class<T> erasure(Type t) {
394 return eraser.visit(t, null);
395 }
396
397 public boolean isAbstract(Class clazz) {
398 return Modifier.isAbstract(clazz.getModifiers());
399 }
400
401 public boolean isFinal(Class clazz) {
402 return Modifier.isFinal(clazz.getModifiers());
403 }
404
405
408 public Type createParameterizedType(Class rawType, Type... arguments) {
409 return new ParameterizedTypeImpl(rawType, arguments, null);
410 }
411
412 public boolean isArray(Type t) {
413 if (t instanceof Class) {
414 Class c = (Class) t;
415 return c.isArray();
416 }
417 if (t instanceof GenericArrayType) {
418 return true;
419 }
420 return false;
421 }
422
423 public boolean isArrayButNotByteArray(Type t) {
424 if (t instanceof Class) {
425 Class c = (Class) t;
426 return c.isArray() && c != byte[].class;
427 }
428 if (t instanceof GenericArrayType) {
429 t = ((GenericArrayType) t).getGenericComponentType();
430 return t != Byte.TYPE;
431 }
432 return false;
433 }
434
435 public Type getComponentType(Type t) {
436 if (t instanceof Class) {
437 Class c = (Class) t;
438 return c.getComponentType();
439 }
440 if (t instanceof GenericArrayType) {
441 return ((GenericArrayType) t).getGenericComponentType();
442 }
443
444 throw new IllegalArgumentException();
445 }
446
447 public Type getTypeArgument(Type type, int i) {
448 if (type instanceof ParameterizedType) {
449 ParameterizedType p = (ParameterizedType) type;
450 return fix(p.getActualTypeArguments()[i]);
451 } else {
452 throw new IllegalArgumentException();
453 }
454 }
455
456 public boolean isParameterizedType(Type type) {
457 return type instanceof ParameterizedType;
458 }
459
460 public boolean isPrimitive(Type type) {
461 if (type instanceof Class) {
462 Class c = (Class) type;
463 return c.isPrimitive();
464 }
465 return false;
466 }
467
468 public Type getPrimitive(Class primitiveType) {
469 assert primitiveType.isPrimitive();
470 return primitiveType;
471 }
472
473 public Location getClassLocation(final Class clazz) {
474 return new Location() {
475
476 @Override
477 public String toString() {
478 return clazz.getName();
479 }
480 };
481 }
482
483 public Location getFieldLocation(final Field field) {
484 return new Location() {
485
486 @Override
487 public String toString() {
488 return field.toString();
489 }
490 };
491 }
492
493 public Location getMethodLocation(final Method method) {
494 return new Location() {
495
496 @Override
497 public String toString() {
498 return method.toString();
499 }
500 };
501 }
502
503 public boolean hasDefaultConstructor(Class c) {
504 try {
505 c.getDeclaredConstructor();
506 return true;
507 } catch (NoSuchMethodException e) {
508 return false;
509 }
510 }
511
512 public boolean isStaticField(Field field) {
513 return Modifier.isStatic(field.getModifiers());
514 }
515
516 public boolean isPublicMethod(Method method) {
517 return Modifier.isPublic(method.getModifiers());
518 }
519
520 public boolean isPublicField(Field field) {
521 return Modifier.isPublic(field.getModifiers());
522 }
523
524 public boolean isEnum(Class c) {
525 return Enum.class.isAssignableFrom(c);
526 }
527
528 public Field[] getEnumConstants(Class clazz) {
529 try {
530 Object[] values = clazz.getEnumConstants();
531 Field[] fields = new Field[values.length];
532 for (int i = 0; i < values.length; i++) {
533 fields[i] = clazz.getField(((Enum) values[i]).name());
534 }
535 return fields;
536 } catch (NoSuchFieldException e) {
537
538 throw new NoSuchFieldError(e.getMessage());
539 }
540 }
541
542 public Type getVoidType() {
543 return Void.class;
544 }
545
546 public String getPackageName(Class clazz) {
547 String name = clazz.getName();
548 int idx = name.lastIndexOf('.');
549 if (idx < 0) {
550 return "";
551 } else {
552 return name.substring(0, idx);
553 }
554 }
555
556 @Override
557 public Class loadObjectFactory(Class referencePoint, String pkg) {
558 ClassLoader cl = SecureLoader.getClassClassLoader(referencePoint);
559 if (cl == null)
560 cl = SecureLoader.getSystemClassLoader();
561
562 try {
563 return cl.loadClass(pkg + ".ObjectFactory");
564 } catch (ClassNotFoundException e) {
565 return null;
566 }
567 }
568
569 public boolean isBridgeMethod(Method method) {
570 return method.isBridge();
571 }
572
573 public boolean isOverriding(Method method, final Class base) {
574
575
576
577
578
579
580
581
582
583
584 final String name = method.getName();
585 final Class[] params = method.getParameterTypes();
586
587 return AccessController.doPrivileged(
588 new PrivilegedAction<Boolean>() {
589
590 @Override
591 public Boolean run() {
592 Class clazz = base;
593 while (clazz != null) {
594 try {
595 Method m = clazz.getDeclaredMethod(name, params);
596 if (m != null) {
597 return Boolean.TRUE;
598 }
599 } catch (NoSuchMethodException ignored) {
600
601 }
602 clazz = clazz.getSuperclass();
603 }
604 return Boolean.FALSE;
605 }
606 }
607 );
608 }
609
610 public boolean isInterface(Class clazz) {
611 return clazz.isInterface();
612 }
613
614 public boolean isTransient(Field f) {
615 return Modifier.isTransient(f.getModifiers());
616 }
617
618 public boolean isInnerClass(Class clazz) {
619 return clazz.getEnclosingClass() != null && !Modifier.isStatic(clazz.getModifiers());
620 }
621
622 @Override
623 public boolean isSameType(Type t1, Type t2) {
624 return t1.equals(t2);
625 }
626
627
633 private Type fix(Type t) {
634 if (!(t instanceof GenericArrayType)) {
635 return t;
636 }
637
638 GenericArrayType gat = (GenericArrayType) t;
639 if (gat.getGenericComponentType() instanceof Class) {
640 Class c = (Class) gat.getGenericComponentType();
641 return Array.newInstance(c, 0).getClass();
642 }
643
644 return t;
645 }
646 }
647