Save This Page
Home » apache-harmony-6.0-src-r917296-snapshot » java » lang » [javadoc | source]
    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   }

Save This Page
Home » apache-harmony-6.0-src-r917296-snapshot » java » lang » [javadoc | source]