001: /*
002: * Copyright 2003-2006 Rick Knowles <winstone-devel at lists sourceforge net>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: */
007: package winstone.classLoader;
008:
009: import java.io.InputStream;
010: import java.net.URL;
011: import java.net.URLClassLoader;
012: import java.net.URLStreamHandlerFactory;
013:
014: import winstone.Logger;
015: import winstone.WinstoneResourceBundle;
016:
017: /**
018: * Implements the servlet spec model (v2.3 section 9.7.2) for classloading, which
019: * is different to the standard JDK model in that it delegates *after* checking
020: * local repositories. This has the effect of isolating copies of classes that exist
021: * in 2 webapps from each other.
022: *
023: * Thanks to James Berry for the changes to use the system classloader to prevent
024: * loading servlet spec or system classpath classes again.
025: *
026: * @author <a href="mailto:rick_knowles@hotmail.com">Rick Knowles</a>
027: * @version $Id: WebappClassLoader.java,v 1.3 2007/12/29 03:32:54 rickknowles Exp $
028: */
029: public class WebappClassLoader extends URLClassLoader {
030: private static final WinstoneResourceBundle CL_RESOURCES = new WinstoneResourceBundle(
031: "winstone.classLoader.LocalStrings");
032:
033: protected ClassLoader system = getSystemClassLoader();
034:
035: public WebappClassLoader(URL[] urls) {
036: super (urls);
037: }
038:
039: public WebappClassLoader(URL[] urls, ClassLoader parent) {
040: super (urls, parent);
041: }
042:
043: public WebappClassLoader(URL[] urls, ClassLoader parent,
044: URLStreamHandlerFactory factory) {
045: super (urls, parent, factory);
046: }
047:
048: protected Class loadClass(String name, boolean resolve)
049: throws ClassNotFoundException {
050: // First, check if the class has already been loaded
051: Class c = findLoadedClass(name);
052:
053: // Try the system loader first, to ensure that system classes are not
054: // overridden by webapps. Note that this includes any classes in winstone,
055: // including the javax.servlet classes
056: if (c == null) {
057: try {
058: c = system.loadClass(name);
059: if (c != null) {
060: Logger.log(Logger.MAX, CL_RESOURCES,
061: "WebappClassLoader.LoadedBySystemCL", name);
062: }
063: } catch (ClassNotFoundException e) {
064: c = null;
065: }
066: }
067:
068: // If an allowed class, load it locally first
069: if (c == null) {
070: try {
071: // If still not found, then invoke findClass in order to find the class.
072: c = findClass(name);
073: if (c != null) {
074: Logger.log(Logger.MAX, CL_RESOURCES,
075: "WebappClassLoader.LoadedByThisCL", name);
076: }
077: } catch (ClassNotFoundException e) {
078: c = null;
079: }
080: }
081:
082: // otherwise, and only if we have a parent, delegate to our parent
083: // Note that within winstone, the only difference between this and the system
084: // class loader we've already tried is that our parent might include the common/shared lib.
085: if (c == null) {
086: ClassLoader parent = getParent();
087: if (parent != null) {
088: c = parent.loadClass(name);
089: if (c != null) {
090: Logger.log(Logger.MAX, CL_RESOURCES,
091: "WebappClassLoader.LoadedByParentCL", name);
092: }
093: } else {
094: // We have no other hope for loading the class, so throw the class not found exception
095: throw new ClassNotFoundException(name);
096: }
097: }
098:
099: if (resolve && (c != null)) {
100: resolveClass(c);
101: }
102: return c;
103: }
104:
105: public InputStream getResourceAsStream(String name) {
106: if ((name != null) && name.startsWith("/")) {
107: name = name.substring(1);
108: }
109: return super.getResourceAsStream(name);
110: }
111: }
|