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   package java.lang;
   18   
   19   import java.io.File;
   20   import java.io.IOException;
   21   import java.io.InputStream;
   22   import java.lang.reflect.Constructor;
   23   import java.net.MalformedURLException;
   24   import java.net.URL;
   25   import java.nio.ByteBuffer;
   26   import java.net.URLClassLoader;
   27   import java.security.AccessController;
   28   import java.security.CodeSource;
   29   import java.security.PrivilegedActionException;
   30   import java.security.PrivilegedExceptionAction;
   31   import java.security.ProtectionDomain;
   32   import java.security.cert.Certificate;
   33   import java.util.ArrayList;
   34   import java.util.Collection;
   35   import java.util.Enumeration;
   36   import java.util.HashMap;
   37   import java.util.Hashtable;
   38   import java.util.NoSuchElementException;
   39   
   40   import org.apache.harmony.lang.RuntimePermissionCollection;
   41   import org.apache.harmony.misc.EmptyEnum;
   42   import org.apache.harmony.lang.ClassLoaderInfo;
   43   import org.apache.harmony.vm.VMStack;
   44   
   45   /**
   46    * Base class for all class loaders
   47    * 
   48    * @author Evgueni Brevnov
   49    */
   50   public abstract class ClassLoader {
   51   
   52       /**
   53        * default protection domain.
   54        */
   55       private ProtectionDomain defaultDomain;
   56   
   57       /**
   58        * system default class loader. It is initialized while
   59        * getSystemClassLoader(..) method is executing.
   60        */
   61       private static ClassLoader systemClassLoader = null;
   62   
   63       /**
   64        * empty set of certificates
   65        */
   66       private static final Certificate[] EMPTY_CERTIFICATES = new Certificate[0];
   67   
   68       /**
   69        * this field has false as default value, it becomes true if system class
   70        * loader is initialized.
   71        */
   72       private static boolean initialized = false;
   73   
   74       /**
   75        * package private to access from the java.lang.Class class. The following
   76        * mapping is used <String name, Boolean flag>, where name - class name,
   77        * flag - true if assertion is enabled, false if disabled.
   78        */
   79       Hashtable<String, Boolean> classAssertionStatus;
   80   
   81       /**
   82        * package private to access from the java.lang.Class class. The following
   83        * mapping is used <String name, Object[] signers>, where name - class name,
   84        * signers - array of signers.
   85        */
   86       Hashtable<String, Object[]> classSigners;
   87   
   88       /**
   89        * package private to access from the java.lang.Class class.
   90        */
   91       int defaultAssertionStatus;
   92       boolean clearAssertionStatus;
   93   
   94       /**
   95        * package private to access from the java.lang.Class class. The following
   96        * mapping is used <String name, Boolean flag>, where name - package name,
   97        * flag - true if assertion is enabled, false if disabled.
   98        */
   99       Hashtable<String, Boolean> packageAssertionStatus;
  100   
  101       /**
  102        * packages defined by this class loader are stored in this hash. The
  103        * following mapping is used <String name, Package pkg>, where name -
  104        * package name, pkg - corresponding package.
  105        */
  106       private final HashMap<String, Package> definedPackages;
  107   
  108       /**
  109        * The class registry, provides strong referencing between the classloader 
  110        * and it's defined classes. Intended for class unloading implementation.
  111        * @see java.lang.Class#definingLoader
  112        * @see #registerLoadedClass()
  113        */
  114       private ArrayList<Class<?>> loadedClasses = new ArrayList<Class<?>>(); 
  115   
  116       /**
  117        * package private to access from the java.lang.Class class. The following
  118        * mapping is used <String name, Certificate[] certificates>, where name -
  119        * the name of a package, certificates - array of certificates.
  120        */
  121       private final Hashtable<String, Certificate[]> packageCertificates = 
  122           new Hashtable<String, Certificate[]>();
  123   
  124       /**
  125        * parent class loader
  126        */
  127       private final ClassLoader parentClassLoader;
  128   
  129       protected ClassLoader() {
  130           this(getSystemClassLoader());
  131       }
  132   
  133       protected ClassLoader(ClassLoader parent) {
  134           SecurityManager sc = System.getSecurityManager();
  135           if (sc != null) {
  136               sc.checkCreateClassLoader();
  137           }
  138           parentClassLoader = parent;
  139           // this field is used to determine whether class loader was initialized
  140           // properly.
  141           definedPackages = new HashMap<String, Package>();
  142       }
  143   
  144       public static ClassLoader getSystemClassLoader() {
  145           if (!initialized) {
  146               // we assume only one thread will initialize system class loader. So
  147               // we don't synchronize initSystemClassLoader() method.
  148               initSystemClassLoader();
  149               // system class loader is initialized properly.
  150               initialized = true;
  151               // setContextClassLoader(...) method throws SecurityException if
  152               // current thread isn't allowed to set systemClassLoader as a
  153               // context class loader. Actually, it is abnormal situation if
  154               // thread can not change his own context class loader.
  155               // Thread.currentThread().setContextClassLoader(systemClassLoader);
  156           }
  157           //assert initialized;
  158           SecurityManager sc = System.getSecurityManager();
  159           if (sc != null) {
  160               // we use VMClassRegistry.getClassLoader(...) method instead of
  161               // Class.getClassLoader() due to avoid redundant security
  162               // checking
  163               ClassLoader callerLoader = VMClassRegistry.getClassLoader(VMStack
  164                   .getCallerClass(0));
  165               if (callerLoader != null && callerLoader != systemClassLoader) {
  166                   sc.checkPermission(RuntimePermissionCollection.GET_CLASS_LOADER_PERMISSION);
  167               }
  168           }
  169           return systemClassLoader;
  170       }
  171   
  172       public static URL getSystemResource(String name) {
  173           return getSystemClassLoader().getResource(name);
  174       }
  175   
  176       public static InputStream getSystemResourceAsStream(String name) {
  177           return getSystemClassLoader().getResourceAsStream(name);
  178       }
  179   
  180       public static Enumeration<URL> getSystemResources(String name)
  181           throws IOException {
  182          return getSystemClassLoader().getResources(name);
  183       }
  184   
  185       public void clearAssertionStatus() {
  186           clearAssertionStatus = true;
  187           defaultAssertionStatus = -1;
  188           packageAssertionStatus = null;
  189           classAssertionStatus = null;
  190       }
  191   
  192       public final ClassLoader getParent() {
  193           SecurityManager sc = System.getSecurityManager();
  194           if (sc != null) {
  195               ClassLoader callerLoader = VMClassRegistry.getClassLoader(VMStack
  196                   .getCallerClass(0));
  197               if (callerLoader != null && !callerLoader.isSameOrAncestor(this)) {
  198                   sc.checkPermission(RuntimePermissionCollection.GET_CLASS_LOADER_PERMISSION);
  199               }
  200           }
  201           return parentClassLoader;
  202       }
  203   
  204       public URL getResource(String name) {
  205           String nm = name.toString();
  206           checkInitialized();
  207           URL foundResource = (parentClassLoader == null)
  208               ? BootstrapLoader.findResource(nm)
  209               : parentClassLoader.getResource(nm);
  210           return foundResource == null ? findResource(nm) : foundResource;
  211       }
  212   
  213       public InputStream getResourceAsStream(String name) {
  214           URL foundResource = getResource(name);
  215           if (foundResource != null) {
  216               try {
  217                   return foundResource.openStream();
  218               } catch (IOException e) {
  219               }
  220           }
  221           return null;
  222       }
  223   
  224       public Enumeration<URL> getResources(String name) throws IOException {
  225           checkInitialized();
  226           ClassLoader cl = this;
  227           final ArrayList<Enumeration<URL>> foundResources = 
  228               new ArrayList<Enumeration<URL>>();
  229           Enumeration<URL> resourcesEnum;
  230           do {
  231               resourcesEnum = cl.findResources(name);
  232               if (resourcesEnum != null && resourcesEnum.hasMoreElements()) {
  233                   foundResources.add(resourcesEnum);
  234               }            
  235           } while ((cl = cl.parentClassLoader) != null);
  236           resourcesEnum = BootstrapLoader.findResources(name);
  237           if (resourcesEnum != null && resourcesEnum.hasMoreElements()) {
  238               foundResources.add(resourcesEnum);
  239           }
  240           return new Enumeration<URL>() {
  241   
  242                   private int position = foundResources.size() - 1;
  243   
  244                   public boolean hasMoreElements() {
  245                       while (position >= 0) {
  246                           if (foundResources.get(position).hasMoreElements()) {
  247                               return true;
  248                           }
  249                           position--;
  250                       }
  251                       return false;
  252                   }
  253   
  254                   public URL nextElement() {
  255                       while (position >= 0) {
  256                           try {
  257                               return (foundResources.get(position)).nextElement();
  258                           } catch (NoSuchElementException e) {}
  259                           position--;
  260                       }
  261                       throw new NoSuchElementException();
  262                   }
  263               };
  264       }
  265   
  266       public Class<?> loadClass(String name) throws ClassNotFoundException {
  267           return loadClass(name, false);
  268       }
  269   
  270       public void setClassAssertionStatus(String name, boolean flag) {
  271           if (name != null) {
  272               Class.disableAssertions = false;
  273               synchronized (definedPackages) {
  274                   if (classAssertionStatus == null) {
  275                       classAssertionStatus = new Hashtable<String, Boolean>();
  276                   }
  277               }
  278               classAssertionStatus.put(name, Boolean.valueOf(flag));
  279           }
  280       }
  281   
  282       public void setDefaultAssertionStatus(boolean flag) {
  283           if (flag) {
  284               Class.disableAssertions = false;
  285           }
  286           defaultAssertionStatus = flag ? 1 : -1;
  287       }
  288   
  289       /**
  290        * Empty string is used to denote default package.
  291        */
  292       public void setPackageAssertionStatus(String name, boolean flag) {
  293           if (name == null) {
  294               name = "";
  295           }
  296           Class.disableAssertions = false;
  297           synchronized (definedPackages) {
  298               if (packageAssertionStatus == null) {
  299                   packageAssertionStatus = new Hashtable<String, Boolean>();
  300               }
  301           }
  302           packageAssertionStatus.put(name, Boolean.valueOf(flag));
  303       }
  304   
  305       @Deprecated
  306       protected final Class<?> defineClass(byte[] data, int offset, int len)
  307           throws ClassFormatError {
  308           return defineClass(null, data, offset, len);
  309       }
  310   
  311       protected final Class<?> defineClass(String name, byte[] data, int offset, int len)
  312           throws ClassFormatError {
  313           return defineClass(name, data, offset, len, null);
  314       }
  315   
  316       /**
  317        * Registers the defined class, invoked by VM.
  318        * Intended for class unloading implementation.
  319        */
  320       @SuppressWarnings("unused") 
  321       private void registerLoadedClass(Class<?> clazz) {
  322           synchronized (loadedClasses){
  323               loadedClasses.add(clazz); 
  324       	}
  325           clazz.definingLoader = this;
  326       }
  327   
  328       protected final Class<?> defineClass(String name, ByteBuffer b, ProtectionDomain protectionDomain)
  329           throws ClassFormatError {
  330   		byte[] data = b.array();
  331           return defineClass(name, data, 0, data.length, protectionDomain);
  332       }
  333   
  334       protected final synchronized Class<?> defineClass(String name, byte[] data,
  335                                                int offset, int len,
  336                                                ProtectionDomain domain)
  337           throws ClassFormatError {
  338           checkInitialized();
  339           if (name != null && name.indexOf('/') != -1) {
  340               throw new NoClassDefFoundError(
  341                       "The name is expected in binary (canonical) form,"
  342                       + " therefore '/' symbols are not allowed: " + name);
  343           }
  344           if (offset < 0 || len < 0 || offset + len > data.length) {
  345               throw new IndexOutOfBoundsException(
  346                   "Either offset or len is outside of the data array");
  347           }
  348           if (domain == null) {
  349               if (defaultDomain == null) {
  350                   defaultDomain = new ProtectionDomain(
  351                           new CodeSource(null, (Certificate[])null), null, this, null);            
  352               }        
  353               domain = defaultDomain;
  354           }
  355           Certificate[] certs = null;
  356           String packageName = null;
  357           if (name != null) {
  358               if (name.startsWith("java.")) {
  359                   throw new SecurityException(
  360                       "It is not allowed to define classes inside the java.* package: " + name);
  361               }
  362               int lastDot = name.lastIndexOf('.');
  363               packageName = lastDot == -1 ? "" : name.substring(0, lastDot);
  364               certs = getCertificates(packageName, domain.getCodeSource());
  365           }
  366           Class<?> clazz = defineClass0(name, data, offset, len);
  367           clazz.setProtectionDomain(domain);
  368           if (certs != null) {
  369               packageCertificates.put(packageName, certs);
  370           }
  371           return clazz;
  372       }
  373       
  374       /**
  375        * Loads new type into the classloader name space. 
  376        * The class loader is marked as defining class loader. 
  377        * @api2vm
  378        */
  379       private native Class<?> defineClass0(String name, byte[] data, int off, int len) 
  380       throws ClassFormatError;
  381   
  382   
  383       protected Package definePackage(String name, String specTitle,
  384                                       String specVersion, String specVendor,
  385                                       String implTitle, String implVersion,
  386                                       String implVendor, URL sealBase)
  387           throws IllegalArgumentException {
  388           synchronized (definedPackages) {
  389               if (getPackage(name) != null) {
  390                   throw new IllegalArgumentException("Package " + name
  391                       + "has been already defined.");
  392               }
  393               Package pkg = new Package(this, name, specTitle, specVersion, specVendor,
  394                   implTitle, implVersion, implVendor, sealBase);
  395               definedPackages.put(name, pkg);
  396               return pkg;
  397           }
  398       }
  399   
  400       protected Class<?> findClass(String name) throws ClassNotFoundException {
  401           throw new ClassNotFoundException("Can not find class " + name);
  402       }
  403   
  404       protected String findLibrary(String name) {
  405           return null;
  406       }
  407   
  408       protected final native Class<?> findLoadedClass(String name);
  409   
  410       protected URL findResource(String name) {
  411           return null;
  412       }
  413   
  414       protected Enumeration<URL> findResources(String name) throws IOException {
  415           return EmptyEnum.getInstance();
  416       }
  417   
  418       protected final Class<?> findSystemClass(String name)
  419           throws ClassNotFoundException {
  420           return getSystemClassLoader().loadClass(name, false);
  421       }
  422   
  423       protected Package getPackage(String name) {
  424           checkInitialized();
  425           Package pkg = null;
  426           if (name == null) {
  427               throw new NullPointerException();
  428           }
  429           synchronized (definedPackages) {
  430               pkg = definedPackages.get(name);
  431           }
  432           if (pkg == null) {
  433               if (parentClassLoader == null) {
  434                   pkg = BootstrapLoader.getPackage(name);
  435               } else {
  436                   pkg = parentClassLoader.getPackage(name);
  437               }
  438           }
  439           return pkg;
  440       }
  441   
  442       protected Package[] getPackages() {
  443           checkInitialized();
  444           ArrayList<Package> packages = new ArrayList<Package>();
  445           fillPackages(packages);
  446           return packages.toArray(new Package[packages.size()]);
  447       }
  448   
  449       /**
  450        * Registers this class loader as initiating for a class
  451        * Declared as package private to use it from java.lang.Class.forName
  452        */
  453       native void registerInitiatedClass(Class<?> clazz);
  454   
  455       protected synchronized Class<?> loadClass(String name, boolean resolve)
  456           throws ClassNotFoundException {
  457           checkInitialized();
  458           if (name == null) {
  459               throw new NullPointerException();
  460           }
  461           if(name.indexOf("/") != -1) {
  462               throw new ClassNotFoundException(name);
  463           }
  464   
  465           Class<?> clazz = findLoadedClass(name);
  466           if (clazz == null) {
  467               if (parentClassLoader == null) {
  468                   clazz = VMClassRegistry.loadBootstrapClass(name);
  469               } else {
  470                   try {
  471                       clazz = parentClassLoader.loadClass(name);
  472                       if(clazz != null) {
  473                           try {
  474                               VMStack.getCallerClass(0)
  475                                       .asSubclass(ClassLoader.class);
  476                           } catch(ClassCastException ex) {
  477                               // caller class is not a subclass of
  478                               // java/lang/ClassLoader so register as
  479                               // initiating loader as we are called from
  480                               // outside of ClassLoader delegation chain
  481                               registerInitiatedClass(clazz);
  482                           }
  483                       }
  484                   } catch (ClassNotFoundException e) {
  485                   }
  486               }
  487               if (clazz == null) {
  488                   clazz = findClass(name);
  489                   if (clazz == null) {
  490                       throw new ClassNotFoundException(name);
  491                   }
  492               }
  493           }
  494           if (resolve) {
  495               resolveClass(clazz);
  496           }
  497           return clazz;
  498       }
  499   
  500       protected final void resolveClass(Class<?> clazz) {
  501           if (clazz == null) {
  502               throw new NullPointerException();
  503           }
  504           VMClassRegistry.linkClass(clazz);
  505       }
  506   
  507       protected final void setSigners(Class<?> clazz, Object[] signers) {
  508           checkInitialized();
  509           String name = clazz.getName();
  510           ClassLoader classLoader = clazz.getClassLoaderImpl();
  511           if (classLoader != null) {
  512               if (classLoader.classSigners == null) {
  513                   classLoader.classSigners = new Hashtable<String, Object[]>();
  514               }
  515               classLoader.classSigners.put(name, signers);
  516           }
  517       }
  518   
  519       /*
  520        * NON API SECTION
  521        */
  522   
  523       final boolean isSameOrAncestor(ClassLoader loader) {
  524           while (loader != null) {
  525               if (this == loader) {
  526                   return true;
  527               }
  528               loader = loader.parentClassLoader;
  529           }
  530           return false;
  531       }
  532   
  533       /**
  534        * This method should be called from each method that performs unsafe
  535        * actions.
  536        */
  537       private void checkInitialized() {
  538           if (definedPackages == null) {
  539               throw new SecurityException(
  540                   "Class loader was not initialized properly.");
  541           }
  542       }
  543   
  544       /**
  545        * Neither certs1 nor certs2 cann't be equal to null.
  546        */
  547       private boolean compareAsSet(Certificate[] certs1, Certificate[] certs2) {
  548           // TODO Is it possible to have multiple instances of same
  549           // certificate in array? This implementation assumes that it is
  550           // not possible.
  551           if (certs1.length != certs1.length) {
  552               return false;
  553           }
  554           if (certs1.length == 0) {
  555               return true;
  556           }
  557           boolean[] hasEqual = new boolean[certs1.length];
  558           for (int i = 0; i < certs1.length; i++) {
  559               boolean isMatch = false;
  560               for (int j = 0; j < certs2.length; j++) {
  561                   if (!hasEqual[j] && certs1[i].equals(certs2[j])) {
  562                       hasEqual[j] = isMatch = true;
  563                       break;
  564                   }
  565               }
  566               if (!isMatch) {
  567                   return false;
  568               }
  569           }
  570           return true;
  571       }
  572   
  573       /**
  574        * Initializes the system class loader.
  575        */
  576       @SuppressWarnings("unchecked")
  577       private static void initSystemClassLoader() {
  578           if (systemClassLoader != null) {
  579               throw new IllegalStateException(
  580                   "Recursive invocation while initializing system class loader");
  581           }
  582           systemClassLoader = SystemClassLoader.getInstance();
  583           
  584           String smName = System.getPropertyUnsecure("java.security.manager");
  585           if (smName != null) {
  586               try {
  587                   final Class<SecurityManager> smClass;
  588                   if ("".equals(smName) || "default".equalsIgnoreCase(smName)) {
  589                       smClass = java.lang.SecurityManager.class;
  590                   } else {
  591                       smClass = (Class<SecurityManager>)systemClassLoader.loadClass(smName);
  592                       if (!SecurityManager.class.isAssignableFrom(smClass)) {
  593                           throw new Error(smClass
  594                               + " must inherit java.lang.SecurityManager");
  595                       }
  596                   }   
  597                   AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
  598                       public Object run() throws Exception {
  599                           System.setSecurityManager(smClass.newInstance());
  600                           return null;
  601                       }
  602                   });
  603               } catch (Exception e) {
  604                   throw (Error)new InternalError().initCause(e);
  605               }
  606           }
  607   
  608           String className = System.getPropertyUnsecure("java.system.class.loader");
  609           if (className != null) {
  610               try {
  611                   final Class<?> userClassLoader = systemClassLoader
  612                       .loadClass(className);
  613                   if (!ClassLoader.class.isAssignableFrom(userClassLoader)) {
  614                       throw new Error(userClassLoader.toString()
  615                           + " must inherit java.lang.ClassLoader");
  616                   }
  617                   systemClassLoader = AccessController
  618                       .doPrivileged(new PrivilegedExceptionAction<ClassLoader>() {
  619                           public ClassLoader run() throws Exception {
  620                               Constructor c = userClassLoader
  621                                   .getConstructor(ClassLoader.class);
  622                               return (ClassLoader)c.newInstance(systemClassLoader);
  623                           }
  624                       });
  625               } catch (ClassNotFoundException e) {
  626                   throw new Error(e);
  627               } catch (PrivilegedActionException e) {
  628                   throw new Error(e.getCause());
  629               }
  630           }
  631       }
  632   
  633       /**
  634        * Helper method for the getPackages() method.
  635        */
  636       private void fillPackages(ArrayList<Package> packages) {
  637           if (parentClassLoader == null) {
  638               packages.addAll(BootstrapLoader.getPackages());
  639           } else {
  640               parentClassLoader.fillPackages(packages);
  641           }
  642           synchronized (definedPackages) {
  643               packages.addAll(definedPackages.values());
  644           }
  645       }
  646   
  647       /**
  648        * Helper method for defineClass(...)
  649        * 
  650        * @return null if the package already has the same set of certificates, if
  651        *         first class in the package is being defined then array of
  652        *         certificates extracted from codeSource is returned.
  653        * @throws SecurityException if the package has different set of
  654        *         certificates than codeSource
  655        */
  656       private Certificate[] getCertificates(String packageName,
  657                                             CodeSource codeSource) {
  658           Certificate[] definedCerts = packageCertificates
  659               .get(packageName);
  660           Certificate[] classCerts = codeSource != null
  661               ? codeSource.getCertificates() : EMPTY_CERTIFICATES;
  662           classCerts = classCerts != null ? classCerts : EMPTY_CERTIFICATES;
  663           // not first class in the package
  664           if (definedCerts != null) {
  665               if (!compareAsSet(definedCerts, classCerts)) {
  666                   throw new SecurityException("It is prohobited to define a "
  667                       + "class which has different set of signers than "
  668                       + "other classes in this package");
  669               }
  670               return null;
  671           }
  672           return classCerts;
  673       }
  674   
  675       /**
  676        * Helper method to avoid StringTokenizer using.
  677        */
  678       private static String[] fracture(String str, String sep) {
  679           if (str.length() == 0) {
  680               return new String[0];
  681           }
  682           ArrayList<String> res = new ArrayList<String>();
  683           int in = 0;
  684           int curPos = 0;
  685           int i = str.indexOf(sep);
  686           int len = sep.length();
  687           while (i != -1) {
  688               String s = str.substring(curPos, i); 
  689               res.add(s);
  690               in++;
  691               curPos = i + len;
  692               i = str.indexOf(sep, curPos);
  693           }
  694   
  695           len = str.length();
  696           if (curPos <= len) {
  697               String s = str.substring(curPos, len); 
  698               in++;
  699               res.add(s);
  700           }
  701   
  702           return res.toArray(new String[in]);
  703       }
  704      
  705       /* IBM SPECIFIC PART */
  706       
  707       static final ClassLoader getStackClassLoader(int depth) {
  708           Class<?> clazz = VMStack.getCallerClass(depth);
  709           return clazz != null ? clazz.getClassLoaderImpl() : null;
  710       }
  711       
  712       final boolean  isSystemClassLoader () {
  713           return ClassLoaderInfo.isSystemClassLoader(this); 
  714       }
  715   
  716       static final void loadLibraryWithClassLoader (String libName, ClassLoader loader) {
  717           SecurityManager sc = System.getSecurityManager();
  718           if (sc != null) {
  719                   sc.checkLink(libName);
  720           }
  721           if (loader != null) {
  722                   String fullLibName = loader.findLibrary(libName);
  723                   if (fullLibName != null) {
  724                           loadLibrary(fullLibName, loader, null);
  725                           return;
  726                   }
  727           }       
  728                   String path = System.getProperty("java.library.path", "");
  729                   path += System.getProperty("vm.boot.library.path", "");
  730           loadLibrary(libName, loader, path);
  731       }
  732      
  733       static final void loadLibrary (String libName, ClassLoader loader, String libraryPath) {
  734           SecurityManager sc = System.getSecurityManager();
  735           if (sc != null) {
  736                   sc.checkLink(libName);
  737           }
  738           String pathSeparator = System.getProperty("path.separator");
  739           String fileSeparator = System.getProperty("file.separator");
  740           String st[] = fracture(libraryPath, pathSeparator);
  741           int l = st.length;
  742           for (int i = 0; i < l; i++) {
  743               try {
  744                   VMClassRegistry.loadLibrary(st[i] + fileSeparator + libName, loader);
  745                   return;
  746               } catch (UnsatisfiedLinkError e) {
  747               }
  748           }
  749           throw new UnsatisfiedLinkError(libName);
  750       } 
  751      
  752       /* END OF IBM SPECIFIC PART */
  753   
  754       static final class BootstrapLoader {
  755   
  756           // TODO avoid security checking
  757           private static final String bootstrapPath = System
  758               .getProperty("vm.boot.class.path", "");
  759   
  760           private static URLClassLoader resourceFinder = null;
  761   
  762           private static final HashMap<String, Package> systemPackages = 
  763               new HashMap<String, Package>();
  764   
  765           /**
  766            * This class contains static methods only. So it should not be
  767            * instantiated.
  768            */
  769           private BootstrapLoader() {
  770           }
  771   
  772           public static URL findResource(String name) {
  773               if (resourceFinder == null) {
  774                   initResourceFinder();
  775               }
  776               return resourceFinder.findResource(name);
  777           }
  778   
  779           public static Enumeration<URL> findResources(String name) throws IOException {
  780               if (resourceFinder == null) {
  781                   initResourceFinder();
  782               }
  783               return resourceFinder.findResources(name);
  784           }
  785   
  786           public static Package getPackage(String name) {
  787               synchronized (systemPackages) {
  788                   updatePackages();
  789                   return systemPackages.get(name.toString());
  790               }
  791           }
  792   
  793           public static Collection<Package> getPackages() {
  794               synchronized (systemPackages) {
  795                   updatePackages();
  796                   return systemPackages.values();
  797               }
  798           }
  799   
  800           private static void initResourceFinder() {
  801               synchronized (bootstrapPath) {
  802                   if (resourceFinder != null) {
  803                       return;
  804                   }                
  805                   // -Xbootclasspath:"" should be interpreted as nothing defined,
  806                   // like we do below:
  807                   String st[] = fracture(bootstrapPath, File.pathSeparator);
  808                   int l = st.length;
  809                   ArrayList<URL> urlList = new ArrayList<URL>();
  810                   for (int i = 0; i < l; i++) {
  811                       try {
  812                           urlList.add(new File(st[i]).toURI().toURL());
  813                       } catch (MalformedURLException e) {
  814                       }
  815                   }
  816                   URL[] urls = new URL[urlList.size()];
  817                   resourceFinder = new URLClassLoader(urlList
  818                       .toArray(urls), null);
  819               }
  820           }
  821   
  822           private static void updatePackages() {
  823               String[][] packages = VMClassRegistry.getSystemPackages(systemPackages.size());
  824               if (null == packages) {
  825                   return;
  826               }
  827               for (int i = 0; i < packages.length; i++) {
  828                   
  829                   String name = packages[i][0];
  830                   if (systemPackages.containsKey(name)) {
  831                       continue;
  832                   }             
  833                   
  834                   String jarURL = packages[i][1];             
  835                   systemPackages.put(name, new Package(null, name, jarURL));
  836               }
  837           }
  838       }
  839   
  840       private static final class SystemClassLoader extends URLClassLoader {
  841   
  842           private boolean checkingPackageAccess = false;
  843   
  844           private SystemClassLoader(URL[] urls, ClassLoader parent) {
  845               super(urls, parent);
  846           }
  847           
  848           @Override
  849           protected java.security.PermissionCollection getPermissions(CodeSource codesource) {
  850               java.security.PermissionCollection pc = super.getPermissions(codesource);
  851               pc.add(org.apache.harmony.lang.RuntimePermissionCollection.EXIT_VM_PERMISSION); 
  852               return pc;
  853           }
  854           
  855           @Override
  856           protected synchronized Class<?> loadClass(String className,
  857                   boolean resolveClass) throws ClassNotFoundException {
  858               SecurityManager sm = System.getSecurityManager();
  859               if (sm != null && !checkingPackageAccess) {
  860                   int index = className.lastIndexOf('.');
  861                   if (index > 0) { // skip if class is from a default package
  862                       try {
  863                           checkingPackageAccess = true;
  864                           sm.checkPackageAccess(className.substring(0, index));
  865                       } finally {
  866                           checkingPackageAccess = false;
  867                       }
  868                   }
  869               }
  870               return super.loadClass(className, resolveClass);
  871           }
  872   
  873           private static URLClassLoader instance;
  874   
  875           static {
  876               ArrayList<URL> urlList = new ArrayList<URL>();
  877               // TODO avoid security checking?
  878               String extDirs = System.getProperty("java.ext.dirs", "");
  879   
  880               // -Djava.ext.dirs="" should be interpreted as nothing defined,
  881               // like we do below:
  882               String st[] = fracture(extDirs, File.pathSeparator);
  883               int l = st.length;
  884               for (int i = 0; i < l; i++) {
  885                   try {
  886                       File dir = new File(st[i]).getAbsoluteFile();
  887                       File[] files = dir.listFiles();
  888                       for (int j = 0; j < files.length; j++) {
  889                           urlList.add(files[j].toURI().toURL());
  890                       }
  891                   } catch (Exception e) {
  892                   }
  893               }
  894               // TODO avoid security checking?
  895               String classPath = System.getProperty("java.class.path",
  896                       File.pathSeparator);
  897               st = fracture(classPath, File.pathSeparator);
  898               l = st.length;
  899               for (int i = 0; i < l; i++) {
  900                   try {
  901                       if(st[i].length() == 0) {
  902                           st[i] = ".";
  903                       }
  904                       urlList.add(new File(st[i]).toURI().toURL());
  905                   } catch (MalformedURLException e) {
  906                       assert false: e.toString();
  907                   }
  908               }
  909               instance = new SystemClassLoader(urlList
  910                   .toArray(new URL[urlList.size()]), null);
  911           }
  912   
  913           public static ClassLoader getInstance() {
  914               return instance;
  915           }
  916       }
  917   }

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