Save This Page
Home » groovy-src-1.6.3 » org.codehaus » groovy » tools » [javadoc | source]
    1   /*
    2    * Copyright 2003-2007 the original author or authors.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *     http://www.apache.org/licenses/LICENSE-2.0
    9    *
   10    * Unless required by applicable law or agreed to in writing, software
   11    * distributed under the License is distributed on an "AS IS" BASIS,
   12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13    * See the License for the specific language governing permissions and
   14    * limitations under the License.
   15    */
   16   package org.codehaus.groovy.tools;
   17   
   18   import java.net.URL;
   19   import java.net.URLClassLoader;
   20   import java.util.Map;
   21   import java.util.HashMap;
   22   
   23   /**
   24    * This ClassLoader should be used as root of class loaders. Any
   25    * RootLoader does have it's own classpath. When searching for a
   26    * class or resource this classpath will be used. Parent
   27    * Classloaders are ignored first. If a class or resource
   28    * can't be found in the classpath of the RootLoader, then parent is
   29    * checked.
   30    * <p/>
   31    * <b>Note:</b> this is very against the normal behavior of
   32    * classloaders. Normal is to first check parent and then look in
   33    * the resources you gave this classloader.
   34    * <p/>
   35    * It's possible to add urls to the classpath at runtime through
   36    * @see #addURL(URL)
   37    *      <p/>
   38    *      <b>Why using RootLoader?</b>
   39    *      If you have to load classes with multiple classloaders and a
   40    *      classloader does know a class which depends on a class only
   41    *      a child of this loader does know, then you won't be able to
   42    *      load the class. To load the class the child is not allowed
   43    *      to redirect it's search for the class to the parent first.
   44    *      That way the child can load the class. If the child does not
   45    *      have all classes to do this, this fails of course.
   46    *      <p/>
   47    *      For example:
   48    *      <p/>
   49    *      <pre>
   50    *       parentLoader   (has classpath: a.jar;c.jar)
   51    *           |
   52    *           |
   53    *       childLoader    (has classpath: a.jar;b.jar;c.jar)
   54    *       </pre>
   55    *      <p/>
   56    *      class C (from c.jar) extends B (from b.jar)
   57    *      <p/>
   58    *      childLoader.find("C")
   59    *      --> parentLoader does know C.class, try to load it
   60    *      --> to load C.class it has to load B.class
   61    *      --> parentLoader is unable to find B.class in a.jar or c.jar
   62    *      --> NoClassDefFoundException!
   63    *      <p/>
   64    *      if childLoader had tried to load the class by itself, there
   65    *      would be no problem. Changing childLoader to be a RootLoader
   66    *      instance will solve that problem.
   67    *
   68    * @author Jochen Theodorou
   69    */
   70   public class RootLoader extends URLClassLoader {
   71   
   72       private Map customClasses = new HashMap();
   73   
   74       /**
   75        * constructs a new RootLoader without classpath
   76        *
   77        * @param parent the parent Loader
   78        */
   79       private RootLoader(ClassLoader parent) {
   80           this(new URL[0], parent);
   81       }
   82   
   83       /**
   84        * constructs a new RootLoader with a parent loader and an
   85        * array of URLs as classpath
   86        */
   87       public RootLoader(URL[] urls, ClassLoader parent) {
   88           super(urls, parent);
   89           // major hack here...!
   90           try{
   91               customClasses.put("org.w3c.dom.Node",super.loadClass("org.w3c.dom.Node",false));
   92           } catch (Exception e) {}
   93       }
   94   
   95       private static ClassLoader chooseParent() {
   96           ClassLoader cl = RootLoader.class.getClassLoader();
   97           if (cl != null) return cl;
   98           return ClassLoader.getSystemClassLoader();
   99       }
  100   
  101       /**
  102        * constructs a new RootLoader with a @see LoaderConfiguration
  103        * object which holds the classpath
  104        */
  105       public RootLoader(LoaderConfiguration lc) {
  106           this(chooseParent());
  107           Thread.currentThread().setContextClassLoader(this);
  108           URL[] urls = lc.getClassPathUrls();
  109           for (int i = 0; i < urls.length; i++) {
  110               addURL(urls[i]);
  111           }
  112       }
  113   
  114       /**
  115        * loads a class using the name of the class
  116        */
  117       protected Class loadClass(final String name, boolean resolve) throws ClassNotFoundException {
  118           Class c = this.findLoadedClass(name);
  119           if (c != null) return c;
  120           c = (Class) customClasses.get(name);
  121           if (c != null) return c;
  122           
  123           try {
  124               c = oldFindClass(name);
  125           } catch (ClassNotFoundException cnfe) {
  126               // IGNORE
  127           }
  128           if (c == null) c = super.loadClass(name, resolve);
  129   
  130           if (resolve) resolveClass(c);
  131   
  132           return c;
  133       }
  134   
  135       /**
  136        * returns the URL of a resource, or null if it is not found
  137        */
  138       public URL getResource(String name) {
  139           URL url = findResource(name);
  140           if (url == null) url = super.getResource(name);
  141           return url;
  142       }
  143   
  144       /**
  145        * adds an url to the classpath of this classloader
  146        */
  147       public void addURL(URL url) {
  148           super.addURL(url);
  149       }
  150   
  151       private Class oldFindClass(String name) throws ClassNotFoundException {
  152           return super.findClass(name);
  153       }
  154   
  155       protected Class findClass(String name) throws ClassNotFoundException {
  156           throw new ClassNotFoundException(name);
  157       }
  158   }

Save This Page
Home » groovy-src-1.6.3 » org.codehaus » groovy » tools » [javadoc | source]