All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.codehaus.groovy.tools.RootLoader Maven / Gradle / Ivy

There is a newer version: 3.0.8-01
Show newest version
/*
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you under the Apache License, Version 2.0 (the
 *  "License"); you may not use this file except in compliance
 *  with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing,
 *  software distributed under the License is distributed on an
 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *  KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations
 *  under the License.
 */
package org.codehaus.groovy.tools;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * This ClassLoader should be used as root of class loaders. Any
 * RootLoader does have its own classpath. When searching for a
 * class or resource this classpath will be used. Parent
 * Classloaders are ignored first. If a class or resource
 * can't be found in the classpath of the RootLoader, then parent is
 * checked.
 * 

* Note: this is very against the normal behavior of * classloaders. Normal is to first check parent and then look in * the resources you gave this classloader. *

* It's possible to add urls to the classpath at runtime through {@link #addURL(URL)}. *

* Why using RootLoader? * If you have to load classes with multiple classloaders and a * classloader does know a class which depends on a class only * a child of this loader does know, then you won't be able to * load the class. To load the class the child is not allowed * to redirect its search for the class to the parent first. * That way the child can load the class. If the child does not * have all classes to do this, this fails of course. *

* For example: *

*

 *       parentLoader   (has classpath: a.jar;c.jar)
 *           |
 *           |
 *       childLoader    (has classpath: a.jar;b.jar;c.jar)
 * 
* * class C (from c.jar) extends B (from b.jar) * * childLoader.find("C") *
 * --> parentLoader does know C.class, try to load it
 * --> to load C.class it has to load B.class
 * --> parentLoader is unable to find B.class in a.jar or c.jar
 * --> NoClassDefFoundException!
 * 
* * if childLoader had tried to load the class by itself, there * would be no problem. Changing childLoader to be a RootLoader * instance will solve that problem. */ public class RootLoader extends URLClassLoader { private static final URL[] EMPTY_URL_ARRAY = new URL[0]; private final Map customClasses = new HashMap(); private static final String ORG_W3C_DOM_NODE = "org.w3c.dom.Node"; /** * constructs a new RootLoader without classpath * * @param parent the parent Loader */ private RootLoader(ClassLoader parent) { this(EMPTY_URL_ARRAY, parent); } /** * constructs a new RootLoader with a parent loader and an * array of URLs as classpath */ public RootLoader(URL[] urls, ClassLoader parent) { super(urls, parent); // major hack here...! try { customClasses.put(ORG_W3C_DOM_NODE, super.loadClass(ORG_W3C_DOM_NODE, false)); } catch (Exception e) { /* ignore */ } } private static ClassLoader chooseParent() { ClassLoader cl = RootLoader.class.getClassLoader(); if (cl != null) return cl; return ClassLoader.getSystemClassLoader(); } /** * constructs a new RootLoader with a {@link LoaderConfiguration} * object which holds the classpath */ public RootLoader(LoaderConfiguration lc) { this(chooseParent()); Thread.currentThread().setContextClassLoader(this); URL[] urls = lc.getClassPathUrls(); for (URL url : urls) { addURL(url); } // TODO M12N eventually defer this until later when we have a full Groovy // environment and use normal Grape.grab() String groovyHome = System.getProperty("groovy.home"); List grabUrls = lc.getGrabUrls(); for (String grabUrl : grabUrls) { Map grabParts = GrapeUtil.getIvyParts(grabUrl); String group = grabParts.get("group").toString(); String module = grabParts.get("module").toString(); String name = grabParts.get("module").toString() + "-" + grabParts.get("version") + ".jar"; File jar = new File(groovyHome + "/repo/" + group + "/" + module + "/jars/" + name); try { addURL(jar.toURI().toURL()); } catch (MalformedURLException e) { // ignore } } } /** * loads a class using the name of the class */ protected synchronized Class loadClass(final String name, boolean resolve) throws ClassNotFoundException { Class c = this.findLoadedClass(name); if (c != null) return c; c = customClasses.get(name); if (c != null) return c; try { c = oldFindClass(name); } catch (ClassNotFoundException cnfe) { // IGNORE } if (c == null) c = super.loadClass(name, resolve); if (resolve) resolveClass(c); return c; } /** * returns the URL of a resource, or null if it is not found */ public URL getResource(String name) { URL url = findResource(name); if (url == null) url = super.getResource(name); return url; } /** * adds an url to the classpath of this classloader */ public void addURL(URL url) { super.addURL(url); } private Class oldFindClass(String name) throws ClassNotFoundException { return super.findClass(name); } protected Class findClass(String name) throws ClassNotFoundException { throw new ClassNotFoundException(name); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy