View Javadoc

    1   /*
    2   $Id: RootLoader.java 3870 2006-06-28 12:59:18Z blackdrag $
    3
    4   Copyright 2003 (C) Jochen Theodorou. All Rights Reserved.
    5
    6   Redistribution and use of this software and associated documentation
    7   ("Software"), with or without modification, are permitted provided
    8   that the following conditions are met:
    9
    10  1. Redistributions of source code must retain copyright
    11     statements and notices.  Redistributions must also contain a
    12     copy of this document.
    13
    14  2. Redistributions in binary form must reproduce the
    15     above copyright notice, this list of conditions and the
    16     following disclaimer in the documentation and/or other
    17     materials provided with the distribution.
    18
    19  3. The name "groovy" must not be used to endorse or promote
    20     products derived from this Software without prior written
    21     permission of The Codehaus.  For written permission,
    22     please contact info@codehaus.org.
    23
    24  4. Products derived from this Software may not be called "groovy"
    25     nor may "groovy" appear in their names without prior written
    26     permission of The Codehaus. "groovy" is a registered
    27     trademark of The Codehaus.
    28
    29  5. Due credit should be given to The Codehaus -
    30     http://groovy.codehaus.org/
    31
    32  THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS
    33  ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
    34  NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
    35  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
    36  THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
    37  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
    38  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    39  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    40  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
    41  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    42  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
    43  OF THE POSSIBILITY OF SUCH DAMAGE.
    44
    45  */
    46  package org.codehaus.groovy.tools;
    47
    48  import java.net.URL;
    49  import java.net.URLClassLoader;
    50
    51  /***
    52   * This ClassLoader should be used as root of class loaders. Any
    53   * RootLoader does have it's own classpath. When searching for a
    54   * class or resource this classpath will be used. Parent
    55   * Classloaders are ignored first. If a class or resource
    56   * can't be found in the classpath of the RootLoader, then parent is
    57   * checked.
    58   *
    59   * <b>Note:</b> this is very against the normal behavior of
    60   * classloaders. Normal is to frist check parent and then look in
    61   * the ressources you gave this classloader.
    62   *
    63   * It's possible to add urls to the classpath at runtime through
    64   * @see #addURL(URL)
    65   *
    66   * <b>Why using RootLoader?</b>
    67   * If you have to load classes with multiple classloaders and a
    68   * classloader does know a class which depends on a class only
    69   * a child of this loader does know, then you won't be able to
    70   * load the class. To load the class the child is not allowed
    71   * to redirect it's search for the class to the parent first.
    72   * That way the child can load the class. If the child does not
    73   * have all classes to do this, this fails of course.
    74   *
    75   * For example:
    76   *
    77   *  <pre>
    78   *  parentLoader   (has classpath: a.jar;c.jar)
    79   *      |
    80   *      |
    81   *  childLoader    (has classpath: a.jar;b.jar;c.jar)
    82   *  </pre>
    83   *
    84   *  class C (from c.jar) extends B (from b.jar)
    85   *
    86   *  childLoader.find("C")
    87   *  --> parentLoader does know C.class, try to load it
    88   *  --> to load C.class it has to load B.class
    89   *  --> parentLoader is unable to find B.class in a.jar or c.jar
    90   *  --> NoClassDefFoundException!
    91   *
    92   *  if childLoader had tried to load the class by itself, there
    93   *  would be no problem. Changing childLoader to be a RootLoader
    94   *  instance will solve that problem.
    95   *
    96   * @author Jochen Theodorou
    97   */
    98  public class RootLoader extends URLClassLoader {
    99
    100     /***
    101      * constructs a new RootLoader without classpath
    102      * @param parent the parent Loader
    103      */
    104     private RootLoader(ClassLoader parent) {
    105         this(new URL[0],parent);
    106     }
    107
    108     /***
    109      * constructs a new RootLoader with a parent loader and an
    110      * array of URLs as classpath
    111      */
    112     public RootLoader(URL[] urls, ClassLoader parent) {
    113         super(urls,parent);
    114     }
    115
    116     private static ClassLoader chooseParent(){
    117       ClassLoader cl = RootLoader.class.getClassLoader();
    118       if (cl!=null) return cl;
    119       return ClassLoader.getSystemClassLoader();
    120     }
    121
    122     /***
    123      * constructs a new RootLoader with a @see LoaderConfiguration
    124      * object which holds the classpath
    125      */
    126     public RootLoader(LoaderConfiguration lc) {
    127         this(chooseParent());
    128         Thread.currentThread().setContextClassLoader(this);
    129         URL[] urls = lc.getClassPathUrls();
    130         for (int i=0; i<urls.length; i++) {
    131             addURL(urls[i]);
    132         }
    133     }
    134
    135     /***
    136      * loads a class using the name of the class
    137      */
    138     protected Class loadClass(final String name, boolean resolve) throws ClassNotFoundException {
    139         Class c = this.findLoadedClass(name);
    140         if (c!=null) return c;
    141
    142         try {
    143             c = findClass(name);
    144         } catch (ClassNotFoundException cnfe) {}
    145         if (c==null) c= super.loadClass(name,resolve);
    146
    147         if (resolve) resolveClass(c);
    148
    149         return c;
    150     }
    151
    152     /***
    153      * returns the URL of a resource, or null if it is not found
    154      */
    155     public URL getResource(String name) {
    156         URL url = findResource(name);
    157         if (url==null) url=super.getResource(name);
    158         return url;
    159     }
    160
    161     /***
    162      * adds an url to the classpath of this classloader
    163      */
    164     public void addURL(URL url) {
    165         super.addURL(url);
    166     }
    167 }