Save This Page
Home » openjdk-7 » java » lang » reflect » [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    * @author Evgueni Brevnov
   19    */
   20   
   21   package java.lang.reflect;
   22   
   23   import org.apache.harmony.lang.reflect.ReflectAccessor;
   24   
   25   /**
   26    * @com.intel.drl.spec_ref 
   27    */
   28   class ReflectExporter implements ReflectAccessor {
   29   
   30       public <T> Constructor<T> copyConstructor(Constructor<T> c) {
   31           return new Constructor<T>(c);
   32       }
   33   
   34       public Field copyField(Field f) {
   35           return new Field(f);
   36       }
   37   
   38       public Method copyMethod(Method m) {
   39           return new Method(m);
   40       }
   41       
   42       public Method[] mergePublicMethods(Method[] declared, 
   43               Method[] superPublic, Method[][] intf, int estimate) {
   44           Method[] store = new Method[estimate];
   45           int size = 0;
   46           for (Method m : declared) {
   47               if (Modifier.isPublic(m.getModifiers())) {
   48                   store[size++] = m;
   49               }
   50           }
   51           if (superPublic != null) {
   52               nextSuper: for (Method m : superPublic) {
   53                   for (int i = 0; i < size; i++) {
   54                       if (m.getName() == store[i].getName() 
   55                               && m.getSignature() == store[i].getSignature()) {
   56                           continue nextSuper;
   57                       }
   58                   }
   59                   store[size++] = m;
   60               }
   61           }
   62           if (intf != null) {
   63               for (Method[] mi : intf) {
   64                   nextIntf: for (Method m : mi) {
   65                       for (int i = 0; i < size; i++) {
   66                           if (m.getName() == store[i].getName() 
   67                                   && m.getSignature() == store[i].getSignature()) {
   68                               continue nextIntf;
   69                           }
   70                       }
   71                       store[size++] = m;                
   72                   }
   73               }
   74           }
   75           Method[] real = new Method[size];
   76           System.arraycopy(store, 0, real, 0, size);
   77   
   78           return real;
   79       }
   80   
   81   
   82       public void checkMemberAccess(Class callerClass, Class declaringClass,
   83                                     Class runtimeClass, int memberModifiers)
   84           throws IllegalAccessException {
   85           if (!allowAccess(callerClass, declaringClass, runtimeClass, memberModifiers)) {
   86               throw new IllegalAccessException("A member of the \""
   87                   + declaringClass + "\" with \""
   88                   + Modifier.toString(memberModifiers)
   89                   + "\" modifiers can not be accessed from the \"" + callerClass
   90                   + "\"");
   91           }
   92       }
   93   
   94       /*
   95        * NON EXPORTED 
   96        */
   97       
   98       private boolean allowAccess(Class<?> callerClass, Class<?> declaringClass,
   99                                   Class<?> runtimeClass, int memberModifiers) {
  100           // it is allways safe to access members from the class declared in the
  101           // same top level class as the declaring class        
  102           if (hasSameTopLevelClass(declaringClass, callerClass)) {
  103               return true;
  104           }
  105           // no way to access private methods at this point
  106           if (Modifier.isPrivate(memberModifiers)) {
  107               return false;
  108           }
  109           // check access to public members
  110           if (Modifier.isPublic(memberModifiers)) {
  111               // fast check
  112               if (allowClassAccess(declaringClass, callerClass)) {
  113                   return true;
  114               }
  115               // full inspection of the hierarchy 
  116               if (runtimeClass != declaringClass) {
  117                   do {
  118                       if (allowClassAccess(runtimeClass, callerClass) ||
  119                           hasSameTopLevelClass(runtimeClass, callerClass)) {
  120                           return true;
  121                       }            
  122                   } while ((runtimeClass = runtimeClass.getSuperclass()) != declaringClass);
  123               }
  124               return  false;
  125           }
  126   
  127           // this check should cover package private access
  128           if (hasSamePackage(declaringClass, callerClass) &&
  129               allowClassAccess(declaringClass, callerClass)) {
  130               return true;
  131           }
  132   
  133           // check access to protected members through hierarchy
  134           if (Modifier.isProtected(memberModifiers)) {            
  135               Class<?> outerClass = callerClass;
  136               // scan from the caller to the top level class
  137               do {
  138                   // find closest enclouser class which extends declaring class
  139                   while (!declaringClass.isAssignableFrom(outerClass)) {
  140                       outerClass = outerClass.getDeclaringClass();
  141                       if (outerClass == null) {
  142                           return false;
  143                       }
  144                   }
  145                   // provide access if and only if outer is subclass of runtime class
  146                   if (outerClass.isAssignableFrom(runtimeClass)) {
  147                       return true;
  148                   }
  149                   outerClass = outerClass.getDeclaringClass();
  150               } while (outerClass != null);
  151           }
  152           return false;
  153       }
  154   
  155       private boolean allowClassAccess(Class<?> callee, Class<?> caller) {
  156           if (callee == null || callee == caller) {
  157               return true;
  158           }
  159           int modifiers = callee.getModifiers();
  160   	    Class calleeDeclaringClass = callee.getDeclaringClass();
  161   	    if (calleeDeclaringClass == null) {
  162   	        // the callee is either a top level class or a local class
  163               if (Modifier.isPublic(modifiers) || hasSamePackage(callee, caller)) {
  164   	            return true;
  165   	        }
  166   	        // other top level classes and local classes 
  167               return false;
  168   	    }
  169   	    // here callee is a member class
  170      	    return allowAccess(caller, calleeDeclaringClass, calleeDeclaringClass, modifiers);
  171       }
  172   
  173       private boolean hasSameTopLevelClass(Class<?> class1, Class<?> class2) {
  174           Class topClass;
  175           while ( (topClass = class1.getEnclosingClass()) != null) {
  176               class1 = topClass;
  177           }
  178           while ( (topClass = class2.getEnclosingClass()) != null) {
  179               class2 = topClass;
  180           }
  181           return class1 == class2;
  182       }
  183   
  184       private boolean hasSamePackage(Class<?> class1, Class<?> class2) {
  185           if (class1.getClassLoader() != class2.getClassLoader()) {
  186               return false;
  187           }
  188           final String pkg1 = class1.getName();
  189           final String pkg2 = class2.getName();
  190           int i1 = pkg1.lastIndexOf('.');
  191           int i2 = pkg2.lastIndexOf('.');
  192           // in the case of default packages i1 == i2 == -1 
  193           return i1 == i2 ? pkg1.regionMatches(0, pkg2, 0, i1) : false;
  194       }
  195   }

Save This Page
Home » openjdk-7 » java » lang » reflect » [javadoc | source]