1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package java.lang;
19
20 import static org.apache.harmony.vm.ClassFormat.ACC_ANNOTATION;
21 import static org.apache.harmony.vm.ClassFormat.ACC_ENUM;
22 import static org.apache.harmony.vm.ClassFormat.ACC_INTERFACE;
23 import static org.apache.harmony.vm.ClassFormat.ACC_SYNTHETIC;
24
25 import java.io.Externalizable;
26 import java.io.InputStream;
27 import java.io.Serializable;
28 import java.lang.annotation.Annotation;
29 import java.lang.annotation.Inherited;
30 import java.lang.ref.SoftReference;
31 import java.lang.reflect.AnnotatedElement;
32 import java.lang.reflect.Constructor;
33 import java.lang.reflect.Field;
34 import java.lang.reflect.GenericDeclaration;
35 import java.lang.reflect.GenericSignatureFormatError;
36 import java.lang.reflect.InvocationTargetException;
37 import java.lang.reflect.MalformedParameterizedTypeException;
38 import java.lang.reflect.Member;
39 import java.lang.reflect.Method;
40 import java.lang.reflect.Modifier;
41 import java.lang.reflect.Type;
42 import java.lang.reflect.TypeVariable;
43 import java.net.URL;
44 import java.security.AccessController;
45 import java.security.AllPermission;
46 import java.security.Permissions;
47 import java.security.PrivilegedAction;
48 import java.security.ProtectionDomain;
49 import java.util.ArrayList;
50 import java.util.Collection;
51 import java.util.LinkedHashSet;
52 import java.util.Map;
53
54 import org.apache.harmony.lang.RuntimePermissionCollection;
55 import org.apache.harmony.lang.reflect.Reflection;
56 import org.apache.harmony.lang.reflect.parser.Parser;
57 import org.apache.harmony.vm.VMGenericsAndAnnotations;
58 import org.apache.harmony.vm.VMStack;
59
60 /**
61 * Runtime representation of a class
62 *
63 * @author Evgueni Brevnov, Serguei S. Zapreyev, Alexey V. Varlamov
64 */
65 public final class Class<T> implements Serializable, AnnotatedElement, GenericDeclaration, Type {
66
67 /**
68 * Global/system assertion status
69 *
70 * package private to access from the java.lang.ClassLoader class.
71 */
72 static volatile boolean disableAssertions =
73 VMExecutionEngine.getAssertionStatus(null, false, 0) <= 0;
74
75 static ProtectionDomain systemDomain;
76
77 private static final long serialVersionUID = 3206093459760846163L;
78
79 private static final Class<Cloneable> CLONEABLE_CLASS = Cloneable.class;
80 @SuppressWarnings("unchecked")
81 private static final Class<Enum> ENUM_CLASS = Enum.class;
82 private static final Class<Externalizable> EXTERNALIZABLE_CLASS = Externalizable.class;
83 private static final Class<Inherited> INHERITED_CLASS = Inherited.class;
84 private static final Class<Object> OBJECT_CLASS = Object.class;
85 private static final Class<Serializable> SERIALIZABLE_CLASS = Serializable.class;
86
87
88 public static Class<?> forName(String name) throws ClassNotFoundException {
89 return forName(name, true, VMClassRegistry.getClassLoader(VMStack
90 .getCallerClass(0)));
91 }
92
93 public static Class<?> forName(String name, boolean initialize,
94 ClassLoader classLoader) throws ClassNotFoundException {
95 if (name == null) {
96 throw new NullPointerException();
97 }
98 if(name.indexOf("/") != -1) {
99 throw new ClassNotFoundException(name);
100 }
101
102 Class<?> clazz = null;
103
104 if (classLoader == null) {
105 SecurityManager sc = System.getSecurityManager();
106 if (sc != null &&
107 VMClassRegistry.getClassLoader(VMStack.getCallerClass(0)) != null) {
108 sc.checkPermission(RuntimePermissionCollection.GET_CLASS_LOADER_PERMISSION);
109 }
110 clazz = VMClassRegistry.loadBootstrapClass(name);
111 } else {
112 int dims = 0;
113 int len = name.length();
114 while (dims < len && name.charAt(dims) == '[') dims++;
115 if (dims > 0 && len > dims + 1
116 && name.charAt(dims) == 'L' && name.endsWith(";")) {
117 /*
118 * an array of a reference type is requested.
119 * do not care of arrays of primitives as
120 * they are perfectly loaded by bootstrap classloader.
121 */
122 try {
123 clazz = classLoader.loadClass(name.substring(dims + 1, len - 1));
124 } catch (ClassNotFoundException ignore) {}
125 if (clazz != null ) {
126 clazz = VMClassRegistry.loadArray(clazz, dims);
127 }
128 } else {
129 clazz = classLoader.loadClass(name);
130 }
131 }
132 if(clazz == null) {
133 throw new ClassNotFoundException(name);
134 }
135 if(classLoader != null) {
136 /*
137 * Although class loader may have had a chance to register itself as
138 * initiating for requested class, there may occur a classloader
139 * which overloads loadClass method (though it is not recommended by
140 * J2SE specification). Try to register initiating loader for clazz
141 * from here again
142 */
143 classLoader.registerInitiatedClass(clazz);
144 }
145 if (initialize) {
146 VMClassRegistry.initializeClass(clazz);
147 } else {
148 VMClassRegistry.linkClass(clazz);
149 }
150 return clazz;
151 }
152
153 /**
154 * VMI method
155 */
156 static final Class<?>[] getStackClasses(int maxDepth, boolean stopAtPrivileged) {
157 return VMStack.getClasses(maxDepth, stopAtPrivileged);
158 }
159
160 /**
161 * Answers whether the arrays are equal
162 */
163 static boolean isTypeMatches(Class<?>[] t1, Class<?>[] t2) {
164 if (t1 == null) {
165 return t2 == null || t2.length == 0;
166 }
167 if (t2 == null) {
168 return t1 == null || t1.length == 0;
169 }
170 if (t1.length != t2.length) {
171 return false;
172 }
173 for (int i = 0; i < t2.length; i++) {
174 if (t1[i] != t2[i]) {
175 return false;
176 }
177 }
178 return true;
179 }
180
181 private static Method findMatchingMethod(Method[] methods,
182 String methodName, Class<?>[] argumentTypes)
183 throws NoSuchMethodException {
184 Method matcher = null;
185 for (int i = 0; i < methods.length; i++) {
186 Method m = methods[i];
187 if (matcher != null
188 && matcher.getDeclaringClass() != m.getDeclaringClass()) {
189 return matcher;
190 }
191 try {
192 if (methodName.equals(m.getName())
193 && isTypeMatches(argumentTypes, m.getParameterTypes())
194 && (matcher == null || matcher.getReturnType()
195 .isAssignableFrom(m.getReturnType()))) {
196 matcher = m;
197 }
198 } catch (LinkageError ignore) {
199 }
200 }
201 if (matcher == null) {
202 throw new NoSuchMethodException(methodName.toString()
203 + printMethodSignature(argumentTypes));
204 }
205 return matcher;
206 }
207
208 private static String getParentName(String name) {
209 int dotPosition = name.lastIndexOf('.');
210 return dotPosition == -1 ? "" : name.substring(0, dotPosition);
211 }
212
213 private static String printMethodSignature(Class<?>[] types) {
214 StringBuffer sb = new StringBuffer("(");
215 if (types != null && types.length > 0) {
216 sb.append(types[0] != null ? types[0].getName() : "null");
217 for (int i = 1; i < types.length; i++) {
218 sb.append(", ");
219 sb.append(types[i] != null ? types[i].getName() : "null");
220 }
221 }
222 sb.append(")");
223 return sb.toString();
224 }
225
226 /**
227 * Provides strong referencing between the classloader
228 * and it's defined classes. Intended for class unloading implementation.
229 * @see java.lang.ClassLoader#loadedClasses
230 */
231 ClassLoader definingLoader;
232
233 transient SoftReference<GACache> softCache;
234
235 private transient volatile ReflectionData _reflectionData;
236
237 private transient ProtectionDomain domain;
238
239 /** It is required for synchronization in newInstance method. */
240 private volatile boolean isDefaultConstructorInitialized;
241
242 /**
243 * Only VM can instantiate this class.
244 */
245 private Class() {
246 }
247
248 /**
249 * Accessor for the reflection data field, which needs to have
250 * minimal thread-safety for consistency; this method encapsulates
251 * that.
252 */
253 private ReflectionData getReflectionData() {
254 // read the volatile field once
255 final ReflectionData localData = _reflectionData;
256 if (localData == null){
257 // if null, construct, write to the field and return
258 return _reflectionData = new ReflectionData();
259 }
260 // else, just return the field
261 return localData;
262 }
263
264 private GACache getCache() {
265 GACache cache = null;
266 if (softCache != null) {
267 cache = softCache.get();
268 }
269 if (cache == null) {
270 softCache = new SoftReference<GACache>(cache = new GACache());
271 }
272 return cache;
273 }
274
275 public boolean desiredAssertionStatus() {
276 if (disableAssertions) {
277 return false;
278 }
279
280 ClassLoader loader = getClassLoaderImpl();
281 if (loader == null) {
282 // system class, status is controlled via cmdline only
283 return VMExecutionEngine.getAssertionStatus(this, true, 0) > 0;
284 }
285
286 // First check exact class name
287 String name = null;
288 Map<String, Boolean> m = loader.classAssertionStatus;
289 if (m != null && m.size() != 0)
290 {
291 name = getTopLevelClassName();
292 Boolean status = m.get(name);
293 if (status != null) {
294 return status.booleanValue();
295 }
296 }
297 if (!loader.clearAssertionStatus) {
298 int systemStatus = VMExecutionEngine.getAssertionStatus(this, false, 0);
299 if (systemStatus != 0) {
300 return systemStatus > 0;
301 }
302 }
303
304 // Next try (super)packages name(s) recursively
305 m = loader.packageAssertionStatus;
306 if (m != null && m.size() != 0) {
307 if (name == null) {
308 name = getName();
309 }
310 name = getParentName(name);
311 // if this class is in the default package,
312 // it is checked in the 1st iteration
313 do {
314 Boolean status = m.get(name);
315 if (status != null) {
316 return status.booleanValue();
317 }
318 } while ( (name = getParentName(name)).length() > 0);
319 }
320 if (!loader.clearAssertionStatus) {
321 int systemStatus = VMExecutionEngine.getAssertionStatus(this, true,
322 loader.defaultAssertionStatus);
323 if (systemStatus != 0) {
324 return systemStatus > 0;
325 }
326 }
327
328 // Finally check the default status
329 return loader.defaultAssertionStatus > 0;
330 }
331
332 /**
333 * Note: We don't check member access permission for each super class.
334 * Java 1.5 API specification doesn't require this check.
335 */
336 public Class[] getClasses() {
337 checkMemberAccess(Member.PUBLIC);
338 Class<?> clss = this;
339 ArrayList<Class<?>> classes = null;
340 while (clss != null) {
341 Class<?>[] declared = VMClassRegistry.getDeclaredClasses(clss);
342 if (declared.length != 0) {
343 if (classes == null) {
344 classes = new ArrayList<Class<?>>();
345 }
346 for (Class<?> c : declared) {
347 if (Modifier.isPublic(c.getModifiers())) {
348 classes.add(c);
349 }
350 }
351 }
352 clss = clss.getSuperclass();
353 }
354 if (classes == null) {
355 return new Class[0];
356 } else {
357 return classes.toArray(new Class[classes.size()]);
358 }
359 }
360
361 public ClassLoader getClassLoader() {
362 ClassLoader loader = getClassLoaderImpl();
363 SecurityManager sc = System.getSecurityManager();
364 if (sc != null) {
365 ClassLoader callerLoader = VMClassRegistry.getClassLoader(VMStack
366 .getCallerClass(0));
367 if (callerLoader != null && !callerLoader.isSameOrAncestor(loader)) {
368 sc.checkPermission(RuntimePermissionCollection.GET_CLASS_LOADER_PERMISSION);
369 }
370 }
371 return loader;
372 }
373
374 public Class<?> getComponentType() {
375 if (!isArray()) {
376 return null;
377 }
378 return VMClassRegistry.getComponentType(this);
379 }
380
381 public Constructor<T> getConstructor(Class... argumentTypes)
382 throws NoSuchMethodException {
383 checkMemberAccess(Member.PUBLIC);
384 Constructor<T> ctors[] = getReflectionData().getPublicConstructors();
385 for (int i = 0; i < ctors.length; i++) {
386 Constructor<T> c = ctors[i];
387 try {
388 if (isTypeMatches(argumentTypes, c.getParameterTypes())) {
389 return Reflection.copyConstructor(c);
390 }
391 } catch (LinkageError ignore) {}
392 }
393 throw new NoSuchMethodException(getName()
394 + printMethodSignature(argumentTypes));
395 }
396
397 @SuppressWarnings("unchecked")
398 public Constructor[] getConstructors() {
399 checkMemberAccess(Member.PUBLIC);
400 return Reflection.copyConstructors(getReflectionData().getPublicConstructors());
401 }
402
403 @SuppressWarnings("unchecked")
404 public Class[] getDeclaredClasses() {
405 checkMemberAccess(Member.DECLARED);
406 return VMClassRegistry.getDeclaredClasses(this);
407 }
408
409 @SuppressWarnings("unchecked")
410 public Constructor<T> getDeclaredConstructor(Class... argumentTypes)
411 throws NoSuchMethodException {
412 checkMemberAccess(Member.DECLARED);
413 return Reflection
414 .copyConstructor(getDeclaredConstructorInternal(argumentTypes));
415 }
416
417 @SuppressWarnings("unchecked")
418 public Constructor[] getDeclaredConstructors() {
419 checkMemberAccess(Member.DECLARED);
420 return Reflection.copyConstructors(getReflectionData().getDeclaredConstructors());
421 }
422
423 public Field getDeclaredField(String fieldName) throws NoSuchFieldException {
424 checkMemberAccess(Member.DECLARED);
425 final Field[] declaredFields = getReflectionData().getDeclaredFields();
426 for (int i = 0; i < declaredFields.length; i++) {
427 Field f = declaredFields[i];
428 if (fieldName.equals(f.getName())) {
429 return Reflection.copyField(f);
430 }
431 }
432 throw new NoSuchFieldException(fieldName.toString());
433 }
434
435 public Field[] getDeclaredFields() {
436 checkMemberAccess(Member.DECLARED);
437 return Reflection.copyFields(getReflectionData().getDeclaredFields());
438 }
439
440 @SuppressWarnings("unchecked")
441 public Method getDeclaredMethod(String methodName, Class... argumentTypes)
442 throws NoSuchMethodException {
443 checkMemberAccess(Member.DECLARED);
444 return Reflection
445 .copyMethod(findMatchingMethod(getReflectionData().getDeclaredMethods(),
446 methodName, argumentTypes));
447 }
448
449 public Method[] getDeclaredMethods() {
450 checkMemberAccess(Member.DECLARED);
451 return Reflection.copyMethods(getReflectionData().getDeclaredMethods());
452 }
453
454 public Class<?> getDeclaringClass() {
455 return VMClassRegistry.getDeclaringClass(this);
456 }
457
458 public Field getField(String fieldName) throws NoSuchFieldException {
459 checkMemberAccess(Member.PUBLIC);
460 final Field[] fields = getReflectionData().getPublicFields();
461 for (Field f : fields) {
462 if (fieldName.equals(f.getName())) {
463 return Reflection.copyField(f);
464 }
465 }
466 throw new NoSuchFieldException(fieldName.toString());
467 }
468
469 public Field[] getFields() {
470 checkMemberAccess(Member.PUBLIC);
471 return Reflection.copyFields(getReflectionData().getPublicFields());
472 }
473
474 @SuppressWarnings("unchecked")
475 public Class[] getInterfaces() {
476 return VMClassRegistry.getInterfaces(this);
477 }
478
479 @SuppressWarnings("unchecked")
480 public Method getMethod(String methodName, Class... argumentTypes)
481 throws NoSuchMethodException {
482 checkMemberAccess(Member.PUBLIC);
483 return Reflection
484 .copyMethod(findMatchingMethod(getReflectionData().getPublicMethods(),
485 methodName, argumentTypes));
486 }
487
488 public Method[] getMethods() {
489 checkMemberAccess(Member.PUBLIC);
490 return Reflection.copyMethods(getReflectionData().getPublicMethods());
491 }
492
493 public int getModifiers() {
494 return getReflectionData().getModifiers();
495 }
496
497 public String getName() {
498 return getReflectionData().name;
499 }
500
501 public Package getPackage() {
502 ClassLoader classLoader = getClassLoaderImpl();
503 return classLoader == null
504 ? ClassLoader.BootstrapLoader.getPackage(getPackageName())
505 : classLoader.getPackage(getPackageName());
506 }
507
508 public ProtectionDomain getProtectionDomain() {
509 SecurityManager sc = System.getSecurityManager();
510 if (sc != null) {
511 sc.checkPermission(
512 RuntimePermissionCollection.GET_PROTECTION_DOMAIN_PERMISSION);
513 }
514 if (domain == null) {
515 if (systemDomain == null) {
516 Permissions allPermissions = new Permissions();
517 allPermissions.add(new AllPermission());
518 systemDomain = new ProtectionDomain(null, allPermissions);
519 }
520 return systemDomain;
521 }
522 return domain;
523 }
524
525 public URL getResource(String resource) {
526 resource = getAbsoluteResource(resource);
527 ClassLoader classLoader = getClassLoaderImpl();
528 return classLoader == null
529 ? ClassLoader.getSystemResource(resource)
530 : classLoader.getResource(resource);
531 }
532
533 public InputStream getResourceAsStream(String resource) {
534 resource = getAbsoluteResource(resource);
535 ClassLoader classLoader = getClassLoaderImpl();
536 return classLoader == null
537 ? ClassLoader.getSystemResourceAsStream(resource)
538 : classLoader.getResourceAsStream(resource);
539 }
540
541 public Object[] getSigners() {
542 try {
543 Object[] signers = (Object[])getClassLoaderImpl().classSigners.get(getName());
544 return (Object[])signers.clone();
545 } catch (NullPointerException e) {
546 }
547 try {
548 return (Object[])domain.getCodeSource().getCertificates().clone();
549 } catch (NullPointerException e) {
550 }
551 return null;
552 }
553
554 public Class<? super T> getSuperclass() {
555 return VMClassRegistry.getSuperclass(this);
556 }
557
558 public boolean isArray() {
559 return getReflectionData().isArray;
560 }
561
562 public boolean isAssignableFrom(Class<?> clazz) {
563
564 if (SERIALIZABLE_CLASS.equals(this)) {
565 return clazz.getReflectionData().isSerializable();
566 }
567
568 if (EXTERNALIZABLE_CLASS.equals(this)) {
569 return clazz.getReflectionData().isExternalizable();
570 }
571
572 return VMClassRegistry.isAssignableFrom(this, clazz);
573 }
574
575 public boolean isInstance(Object obj) {
576 return VMClassRegistry.isInstance(this, obj);
577 }
578
579 public boolean isInterface() {
580 return (getModifiers() & ACC_INTERFACE) != 0;
581 }
582
583 public boolean isPrimitive() {
584 return getReflectionData().isPrimitive;
585 }
586
587 public T newInstance() throws InstantiationException,
588 IllegalAccessException {
589 T newInstance = null;
590 final ReflectionData localReflectionData = getReflectionData();
591 SecurityManager sc = System.getSecurityManager();
592 if (sc != null) {
593 sc.checkMemberAccess(this, Member.PUBLIC);
594 sc.checkPackageAccess(localReflectionData.packageName);
595 }
596
597 /*
598 * HARMONY-1930: The synchronization issue is possible here.
599 *
600 * The issues is caused by fact that:
601 * - first thread starts defaultConstructor initialization, including
602 * setting "isAccessible" flag to "true" for Constrcutor object
603 * - another thread bypasses initialization and calls "newInstance"
604 * for defaultConstructor (while isAccessible is "false" yet)
605 * - so, for this "another" thread the Constructor.newInstance checks
606 * the access rights by mistake and IllegalAccessException happens
607 */
608 while (!isDefaultConstructorInitialized) {
609 synchronized (localReflectionData) {
610 if (isDefaultConstructorInitialized) {
611 break; // non-first threads can be here - nothing to do
612 }
613
614 // only first thread can reach this point & do initialization
615 final Constructor<T> c;
616 try {
617 c = localReflectionData.getDefaultConstructor();
618 } catch (NoSuchMethodException e) {
619 throw new InstantiationException(e.getMessage()
620 + " method not found");
621 }
622 try {
623 AccessController.doPrivileged(new PrivilegedAction<Object>() {
624 public Object run() {
625 c.setAccessible(true);
626 return null;
627 }
628 });
629 } catch (SecurityException e) {
630 // can't change accessibility of the default constructor
631 IllegalAccessException ex = new IllegalAccessException();
632 ex.initCause(e);
633 throw ex;
634 }
635
636 // default constructor is initialized, access flag is set
637 isDefaultConstructorInitialized = true;
638 break;
639 }
640 }
641
642 // initialization is done, threads may work from here in any order
643 final Constructor<T> defaultConstructor;
644 try {
645 defaultConstructor = localReflectionData.getDefaultConstructor();
646 } catch (NoSuchMethodException e){
647 throw new AssertionError(e);
648 }
649 Reflection.checkMemberAccess(
650 VMStack.getCallerClass(0),
651 defaultConstructor.getDeclaringClass(),
652 defaultConstructor.getDeclaringClass(),
653 defaultConstructor.getModifiers()
654 );
655
656 try {
657 newInstance = defaultConstructor.newInstance();
658 } catch (InvocationTargetException e) {
659 System.rethrow(e.getCause());
660 }
661 return newInstance;
662 }
663
664 @Override
665 public String toString() {
666 return isPrimitive() ? getName()
667 : (isInterface() ? "interface " : "class ") + getName();
668 }
669
670 String getPackageName() {
671 return getReflectionData().packageName;
672 }
673
674 void setProtectionDomain(ProtectionDomain protectionDomain) {
675 domain = protectionDomain;
676 }
677
678 private void checkMemberAccess(int accessType) {
679 SecurityManager sc = System.getSecurityManager();
680 if (sc != null) {
681 sc.checkMemberAccess(this, accessType);
682 sc.checkPackageAccess(getReflectionData().packageName);
683 }
684 }
685
686 private String getAbsoluteResource(String resource) {
687 if (resource.startsWith("/")) {
688 return resource.substring(1);
689 }
690 String pkgName = getPackageName();
691 if (pkgName.length() > 0) {
692 resource = pkgName.replace('.', '/') + '/' + resource;
693 }
694 return resource;
695 }
696
697 private Constructor<T> getDeclaredConstructorInternal(Class<?>[] argumentTypes)
698 throws NoSuchMethodException {
699 final Constructor<T>[] declaredConstructors = getReflectionData().getDeclaredConstructors();
700 for (int i = 0; i < declaredConstructors.length; i++) {
701 Constructor<T> c = declaredConstructors[i];
702 if (isTypeMatches(argumentTypes, c.getParameterTypes())) {
703 return c;
704 }
705 }
706 throw new NoSuchMethodException(getName()
707 + printMethodSignature(argumentTypes));
708 }
709
710 private String getTopLevelClassName() {
711 Class<?> declaringClass = getDeclaringClass();
712 return declaringClass == null
713 ? getName() : declaringClass.getTopLevelClassName();
714 }
715
716 /**
717 * VMI method
718 */
719 final ClassLoader getClassLoaderImpl() {
720 assert(VMClassRegistry.getClassLoader0(this) == definingLoader);
721 return definingLoader;
722 }
723
724 public Annotation[] getDeclaredAnnotations() {
725 Annotation[] declared = getCache().getDeclaredAnnotations();
726 Annotation aa[] = new Annotation[declared.length];
727 System.arraycopy(declared, 0, aa, 0, declared.length);
728 return aa;
729 }
730
731 public Annotation[] getAnnotations() {
732 Annotation[] all = getCache().getAllAnnotations();
733 Annotation aa[] = new Annotation[all.length];
734 System.arraycopy(all, 0, aa, 0, all.length);
735 return aa;
736 }
737
738 @SuppressWarnings("unchecked")
739 public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {
740 if(annotationClass == null) {
741 throw new NullPointerException();
742 }
743 for (Annotation aa : getCache().getAllAnnotations()) {
744 if(annotationClass == aa.annotationType()) {
745 return (A)aa;
746 }
747 }
748 return null;
749 }
750
751 public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {
752 if(annotationClass == null) {
753 throw new NullPointerException();
754 }
755 for (Annotation aa : getCache().getAllAnnotations()) {
756 if(annotationClass == aa.annotationType()) {
757 return true;
758 }
759 }
760 return false;
761 }
762
763 @SuppressWarnings("unchecked")
764 public T[] getEnumConstants() {
765 if (isEnum()) {
766 try {
767 final Method values = getMethod("values");
768 AccessController.doPrivileged(new PrivilegedAction() {
769 public Object run() {
770 values.setAccessible(true);
771 return null;
772 }
773 });
774 return (T[]) values.invoke(null);
775 } catch (Exception ignore) {}
776 }
777 return null;
778 }
779
780 public boolean isEnum() {
781 // check for superclass is needed for compatibility
782 // otherwise there are false positives on anonymous element classes
783 return ((getModifiers() & ACC_ENUM) != 0 && getSuperclass() == ENUM_CLASS);
784 }
785
786 public boolean isAnnotation() {
787 return (getModifiers() & ACC_ANNOTATION) != 0;
788 }
789
790 @SuppressWarnings("unchecked")
791 public <U> Class<? extends U> asSubclass(Class<U> clazz) throws ClassCastException {
792 if (!VMClassRegistry.isAssignableFrom(clazz, this)) {
793 throw new ClassCastException(toString());
794 }
795
796 return (Class<? extends U>)this;
797 }
798
799 @SuppressWarnings("unchecked")
800 public T cast(Object obj) throws ClassCastException {
801 if (obj != null && !VMClassRegistry.isInstance(this, obj)) {
802 throw new ClassCastException(obj.getClass().toString());
803 }
804 return (T) obj;
805 }
806
807 public TypeVariable<Class<T>>[] getTypeParameters() throws GenericSignatureFormatError {
808 return (TypeVariable<Class<T>>[])getCache().getTypeParameters().clone();
809 }
810
811 public Method getEnclosingMethod() {
812 Member m = VMClassRegistry.getEnclosingMember(this); // see VMClassRegistry.getEnclosingMember() spec
813 return m instanceof Method? (Method)m : null;
814 }
815
816 public Constructor<?> getEnclosingConstructor() {
817 Member m = VMClassRegistry.getEnclosingMember(this); // see VMClassRegistry.getEnclosingMember() spec
818 return m instanceof Constructor ? (Constructor<?>)m : null;
819 }
820
821 public Type[] getGenericInterfaces() throws GenericSignatureFormatError, TypeNotPresentException, MalformedParameterizedTypeException {
822 if (isArray()) {
823 return new Type[]{CLONEABLE_CLASS, SERIALIZABLE_CLASS};
824 }
825 if (isPrimitive()) {
826 return new Type[0];
827 }
828
829 return (Type[])getCache().getGenericInterfaces().clone();
830 }
831
832 public Type getGenericSuperclass() throws GenericSignatureFormatError, TypeNotPresentException, MalformedParameterizedTypeException {
833 String tmp;
834 if (isInterface() || ((tmp = getCanonicalName()) != null && tmp.equals("java.lang.Object")) || isPrimitive()) {
835 return null;
836 }
837 if (isArray()) {
838 return (Type) OBJECT_CLASS;
839 }
840
841 Class<?> clazz = getSuperclass();
842 if (clazz.getTypeParameters().length == 0) {
843 return (Type) clazz;
844 }
845
846 return getCache().getGenericSuperclass();
847 }
848
849 public Class<?> getEnclosingClass() {
850 return VMClassRegistry.getEnclosingClass(this); // see VMClassRegistry.getEnclosingClass() spec
851 }
852
853 public boolean isMemberClass() {
854 return getDeclaringClass() != null; // see Class.getDeclaringClass() spec
855 }
856
857 public boolean isLocalClass() {
858 return VMClassRegistry.getEnclosingMember(this) != null && !isAnonymousClass(); // see CFF spec, #4.8.6, first paragraph and VMClassRegistry.getEnclosingMember() spec
859 }
860
861
862 public boolean isAnonymousClass() {
863 return getSimpleName().length() == 0;
864 }
865
866 public boolean isSynthetic() {
867 return (getModifiers() & ACC_SYNTHETIC) != 0;
868 }
869
870 public String getCanonicalName() {
871 if (isLocalClass() || isAnonymousClass()) {
872 return null;
873 }
874 if (isArray()) {
875 String res = getComponentType().getCanonicalName();
876 return res != null ? res + "[]" : null;
877 }
878
879 StringBuffer sb = new StringBuffer(getPackageName());
880 ArrayList<String> sympleNames = new ArrayList<String>();
881 Class<?> clss = this;
882 while ((clss = clss.getDeclaringClass()) != null) {
883 if (clss.isLocalClass() || clss.isAnonymousClass()) {
884 return null;
885 }
886 sympleNames.add(clss.getSimpleName());
887 }
888 if (sb.length() > 0) {
889 sb.append(".");
890 }
891 for (int i = sympleNames.size() - 1; i > -1 ; i--) {
892 sb.append(sympleNames.get(i)).append(".");
893 }
894 sb.append(getSimpleName());
895
896 return sb.toString();
897 }
898
899 public String getSimpleName() {
900 return VMClassRegistry.getSimpleName(this);
901 }
902
903 private final class ReflectionData {
904
905 final String packageName;
906 final String name;
907 final boolean isPrimitive;
908 final boolean isArray;
909
910 /*
911 * Do no access the following fields directly from enclosing class;
912 * use the accessor methods
913 */
914 private volatile int _modifiers;
915 private volatile Constructor<T>[] _declaredConstructors;
916 private volatile Field[] _declaredFields;
917 private volatile Method[] _declaredMethods;
918 private volatile Constructor<T> _defaultConstructor;
919 private volatile Constructor<T>[] _publicConstructors;
920 private volatile Field[] _publicFields;
921 private volatile Method[] _publicMethods;
922
923 private volatile boolean _serialPropsResolved;
924 private boolean _isExternalizable;
925 private boolean _isSerializable;
926
927 ReflectionData() {
928 name = VMClassRegistry.getName(Class.this);
929 isPrimitive = VMClassRegistry.isPrimitive(Class.this);
930 isArray = VMClassRegistry.isArray(Class.this);
931 packageName = Class.getParentName(name);
932 _modifiers = -1;
933 }
934
935 boolean isSerializable(){
936 resolveSerialProps();
937 return _isSerializable;
938 }
939
940 boolean isExternalizable() {
941 resolveSerialProps();
942 return _isExternalizable;
943 }
944
945 private void resolveSerialProps() {
946 if (!_serialPropsResolved){
947 _isExternalizable = VMClassRegistry.isAssignableFrom(EXTERNALIZABLE_CLASS, Class.this);
948 _isSerializable = VMClassRegistry.isAssignableFrom(SERIALIZABLE_CLASS, Class.this);
949 _serialPropsResolved = true;
950 }
951 }
952
953 int getModifiers() {
954 final int localCopy = _modifiers;
955 if (localCopy != -1){
956 return localCopy;
957 }
958 return _modifiers = VMClassRegistry.getModifiers(Class.this);
959 }
960
961 Constructor<T>[] getDeclaredConstructors() {
962 final Constructor<T>[] localCopy = _declaredConstructors;
963 if (localCopy != null) {
964 return localCopy;
965 }
966 return _declaredConstructors = VMClassRegistry.getDeclaredConstructors(Class.this);
967 }
968
969 Field[] getDeclaredFields() {
970 final Field[] localCopy = _declaredFields;
971 if (localCopy == null) {
972 return _declaredFields = VMClassRegistry
973 .getDeclaredFields(Class.this);
974 } else {
975 return localCopy;
976 }
977 }
978
979 Method[] getDeclaredMethods() {
980 final Method[] localCopy = _declaredMethods;
981 if (localCopy != null) {
982 return localCopy;
983 }
984 return _declaredMethods = VMClassRegistry.getDeclaredMethods(Class.this);
985 }
986
987 Constructor<T> getDefaultConstructor() throws NoSuchMethodException {
988 final Constructor<T> localCopy = _defaultConstructor;
989 if (localCopy != null) {
990 return localCopy;
991 }
992 return _defaultConstructor = Class.this.getDeclaredConstructorInternal(null);
993 }
994
995 Constructor<T>[] getPublicConstructors() {
996 final Constructor<T>[] localCopy = _publicConstructors;
997 if (localCopy != null) {
998 return localCopy;
999 }
1000
1001 final Constructor<T>[] declaredConstructors = getDeclaredConstructors();
1002 ArrayList<Constructor<T>> constructors = new ArrayList<Constructor<T>>(
1003 declaredConstructors.length);
1004 for (int i = 0; i < declaredConstructors.length; i++) {
1005 Constructor<T> c = declaredConstructors[i];
1006 if (Modifier.isPublic(c.getModifiers())) {
1007 constructors.add(c);
1008 }
1009 }
1010 final int size = constructors.size();
1011 @SuppressWarnings("unchecked")
1012 final Constructor<T>[] tempArray = (Constructor<T>[]) new Constructor[size];
1013 return _publicConstructors = constructors.toArray(tempArray);
1014 }
1015
1016 /**
1017 * Stores public fields in order they should be searched by
1018 * getField(name) method.
1019 */
1020 public synchronized Field[] getPublicFields() {
1021 final Field[] localCopy = _publicFields;
1022 if (localCopy != null) {
1023 return localCopy;
1024 }
1025
1026 final Field[] declaredFields = getDeclaredFields();
1027
1028 // initialize public fields of the super class
1029 int size = declaredFields.length;
1030 Class<?> superClass = Class.this.getSuperclass();
1031 Field[] superFields = null;
1032 if (superClass != null) {
1033 final Class<?>.ReflectionData superClassRefData = superClass.getReflectionData();
1034 superFields = superClassRefData.getPublicFields();
1035 size += superFields.length;
1036 }
1037
1038 // add public fields of this class
1039 Collection<Field> fields = new LinkedHashSet<Field>(size);
1040 for (Field f : declaredFields) {
1041 if (Modifier.isPublic(f.getModifiers())) {
1042 fields.add(f);
1043 }
1044 }
1045
1046 // initialize and add fields of the super interfaces
1047 Class<?>[] interfaces = Class.this.getInterfaces();
1048 for (Class<?> ci : interfaces) {
1049 final Class<?>.ReflectionData ciRefData = ci.getReflectionData();
1050 Field[] fi = ciRefData.getPublicFields();
1051 for (Field f : fi) {
1052 fields.add(f);
1053 }
1054 }
1055
1056 // add public fields of the super class
1057 if (superFields != null) {
1058 for (Field f : superFields) {
1059 if (Modifier.isPublic(f.getModifiers())) {
1060 fields.add(f);
1061 }
1062 }
1063 }
1064
1065 return _publicFields = fields.toArray(new Field[fields.size()]);
1066 }
1067
1068 public synchronized Method[] getPublicMethods() {
1069 final Method[] localCopy = _publicMethods;
1070 if (localCopy != null) {
1071 return localCopy;
1072 }
1073
1074 final Method[] declaredMethods = getDeclaredMethods();
1075
1076 // initialize public methods of the super class
1077 int size = declaredMethods.length;
1078 Class<?> superClass = Class.this.getSuperclass();
1079 Method[] superPublic = null;
1080 if (superClass != null) {
1081 final Class<?>.ReflectionData superClassRefData = superClass.getReflectionData();
1082 superPublic = superClassRefData.getPublicMethods();
1083 size += superPublic.length;
1084 }
1085
1086 // add methods of the super interfaces
1087 Class<?>[] interfaces = Class.this.getInterfaces();
1088 Method[][] intf = null;
1089 if (interfaces.length != 0) {
1090 intf = new Method[interfaces.length][];
1091 for (int i = 0; i < interfaces.length; i++) {
1092 Class<?> ci = interfaces[i];
1093 final Class<?>.ReflectionData ciRefData = ci.getReflectionData();
1094 intf[i] = ciRefData.getPublicMethods();
1095 size += intf[i].length;
1096 }
1097 }
1098 return _publicMethods = Reflection.mergePublicMethods(declaredMethods, superPublic, intf, size);
1099 }
1100 }
1101
1102 private final class GACache {
1103
1104 private Annotation[] allAnnotations;
1105 private Annotation[] declaredAnnotations;
1106 private Type[] genericInterfaces;
1107 private Type genericSuperclass;
1108 private TypeVariable<Class<T>>[] typeParameters;
1109
1110 public synchronized Annotation[] getAllAnnotations() {
1111 if (allAnnotations != null) {
1112 return allAnnotations;
1113 }
1114 if (declaredAnnotations == null) {
1115 declaredAnnotations = VMGenericsAndAnnotations
1116 .getDeclaredAnnotations(Class.this);
1117 }
1118
1119 // look for inherited annotations
1120 Class<?> superClass = Class.this.getSuperclass();
1121 if (superClass != null) {
1122 Annotation[] sa = superClass.getCache().getAllAnnotations();
1123 if (sa.length != 0) {
1124 final int size = declaredAnnotations.length;
1125 Annotation[] all = new Annotation[size + sa.length];
1126 System.arraycopy(declaredAnnotations, 0, all, 0, size);
1127 int pos = size;
1128 next: for (Annotation s : sa) {
1129 if (s.annotationType().isAnnotationPresent(INHERITED_CLASS)) {
1130 for (int i = 0; i < size; i++) {
1131 if (all[i].annotationType() == s.annotationType()) {
1132 // overriden by declared annotation
1133 continue next;
1134 }
1135 }
1136 all[pos++] = s;
1137 }
1138 }
1139 allAnnotations = new Annotation[pos];
1140 System.arraycopy(all, 0, allAnnotations, 0, pos);
1141 return allAnnotations;
1142 }
1143 }
1144 return allAnnotations = declaredAnnotations;
1145 }
1146
1147 public Annotation[] getDeclaredAnnotations() {
1148 if (declaredAnnotations == null) {
1149 declaredAnnotations = VMGenericsAndAnnotations
1150 .getDeclaredAnnotations(Class.this);
1151 }
1152 return declaredAnnotations;
1153 }
1154
1155 public synchronized Type[] getGenericInterfaces() {
1156 if (genericInterfaces == null) {
1157 genericInterfaces = Parser.getGenericInterfaces(Class.this, VMGenericsAndAnnotations.getSignature(Class.this));
1158 }
1159 return genericInterfaces;
1160 }
1161
1162 public Type getGenericSuperclass() {
1163 //So, here it can be only ParameterizedType or ordinary reference class type
1164 if (genericSuperclass == null) {
1165 genericSuperclass = Parser.getGenericSuperClass(Class.this, VMGenericsAndAnnotations.getSignature(Class.this));
1166 }
1167 return genericSuperclass;
1168 }
1169
1170 @SuppressWarnings("unchecked")
1171 public synchronized TypeVariable<Class<T>>[] getTypeParameters() {
1172 if(typeParameters == null){
1173 typeParameters = Parser.getTypeParameters(Class.this,
1174 VMGenericsAndAnnotations.getSignature(Class.this));
1175 }
1176 return typeParameters;
1177 }
1178 }
1179 }