Java tutorial
// ======================================================================== // $Id: ContextLoader.java,v 1.37 2006/01/09 07:26:12 gregwilkins Exp $ // Copyright 1999-2004 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // Licensed 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 net.lightbody.bmp.proxy.jetty.http; import net.lightbody.bmp.proxy.jetty.log.LogFactory; import net.lightbody.bmp.proxy.jetty.util.IO; import net.lightbody.bmp.proxy.jetty.util.Resource; import org.apache.commons.logging.Log; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.security.CodeSource; import java.security.PermissionCollection; import java.util.Arrays; import java.util.StringTokenizer; /* ------------------------------------------------------------ */ /** ClassLoader for HttpContext. * Specializes URLClassLoader with some utility and file mapping * methods. * * This loader defaults to the 2.3 servlet spec behaviour where non * system classes are loaded from the classpath in preference to the * parent loader. Java2 compliant loading, where the parent loader * always has priority, can be selected with the setJava2Complient method. * * @version $Id: ContextLoader.java,v 1.37 2006/01/09 07:26:12 gregwilkins Exp $ * @author Greg Wilkins (gregw) */ public class ContextLoader extends URLClassLoader { private static Log log = LogFactory.getLog(ContextLoader.class); private boolean _java2compliant = false; private ClassLoader _parent; private PermissionCollection _permissions; private String _urlClassPath; private HttpContext _context; /* ------------------------------------------------------------ */ /** Constructor. * @param classPath Comma separated path of filenames or URLs * pointing to directories or jar files. Directories should end * with '/'. * @exception IOException */ public ContextLoader(HttpContext context, String classPath, ClassLoader parent, PermissionCollection permisions) throws MalformedURLException, IOException { super(new URL[0], parent); _context = context; _permissions = permisions; _parent = parent; if (_parent == null) _parent = getSystemClassLoader(); if (classPath == null) { _urlClassPath = ""; } else { StringTokenizer tokenizer = new StringTokenizer(classPath, ",;"); while (tokenizer.hasMoreTokens()) { Resource resource = Resource.newResource(tokenizer.nextToken()); if (log.isDebugEnabled()) log.debug("Path resource=" + resource); // Resolve file path if possible File file = resource.getFile(); if (file != null) { URL url = resource.getURL(); addURL(url); _urlClassPath = (_urlClassPath == null) ? url.toString() : (_urlClassPath + "," + url.toString()); } else { // Add resource or expand jar/ if (!resource.isDirectory() && file == null) { InputStream in = resource.getInputStream(); File lib = new File(context.getTempDirectory(), "lib"); if (!lib.exists()) { lib.mkdir(); lib.deleteOnExit(); } File jar = File.createTempFile("Jetty-", ".jar", lib); jar.deleteOnExit(); if (log.isDebugEnabled()) log.debug("Extract " + resource + " to " + jar); FileOutputStream out = null; try { out = new FileOutputStream(jar); IO.copy(in, out); } finally { IO.close(out); } URL url = jar.toURL(); addURL(url); _urlClassPath = (_urlClassPath == null) ? url.toString() : (_urlClassPath + "," + url.toString()); } else { URL url = resource.getURL(); addURL(url); _urlClassPath = (_urlClassPath == null) ? url.toString() : (_urlClassPath + "," + url.toString()); } } } } if (log.isDebugEnabled()) { if (log.isDebugEnabled()) log.debug("ClassPath=" + _urlClassPath); if (log.isDebugEnabled()) log.debug("Permissions=" + _permissions); if (log.isDebugEnabled()) log.debug("URL=" + Arrays.asList(getURLs())); } } /* ------------------------------------------------------------ */ /** Set Java2 compliant status. * @param compliant */ public void setJava2Compliant(boolean compliant) { _java2compliant = compliant; } /* ------------------------------------------------------------ */ public boolean isJava2Compliant() { return _java2compliant; } /* ------------------------------------------------------------ */ public String toString() { return "ContextLoader@" + hashCode() + "(" + _urlClassPath + ")\n --parent--> " + _parent.toString(); } /* ------------------------------------------------------------ */ public PermissionCollection getPermissions(CodeSource cs) { PermissionCollection pc = (_permissions == null) ? super.getPermissions(cs) : _permissions; if (log.isDebugEnabled()) log.debug("loader.getPermissions(" + cs + ")=" + pc); return pc; } /* ------------------------------------------------------------ */ public Class loadClass(String name) throws ClassNotFoundException { return loadClass(name, false); } /* ------------------------------------------------------------ */ protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { Class c = findLoadedClass(name); ClassNotFoundException ex = null; boolean tried_parent = false; if (c == null && (_java2compliant || isSystemPath(name)) && !isServerPath(name) && _parent != null) { if (log.isTraceEnabled()) log.trace("try loadClass " + name + " from " + _parent); tried_parent = true; try { c = _parent.loadClass(name); if (log.isTraceEnabled()) log.trace("p0 loaded " + c); } catch (ClassNotFoundException e) { ex = e; } } if (c == null) { if (log.isTraceEnabled()) log.trace("try findClass " + name + " from " + _urlClassPath); try { c = this.findClass(name); if (log.isTraceEnabled()) log.trace("cx loaded " + c); } catch (ClassNotFoundException e) { ex = e; } } if (c == null && !tried_parent && !isServerPath(name) && _parent != null) { if (log.isTraceEnabled()) log.trace("try loadClass " + name + " from " + _parent); c = _parent.loadClass(name); if (log.isTraceEnabled()) log.trace("p1 loaded " + c); } if (c == null) throw ex; if (resolve) resolveClass(c); return c; } /* ------------------------------------------------------------ */ public URL getResource(String name) { URL url = null; boolean tried_parent = false; if (_parent != null && (_java2compliant || isSystemPath(name))) { if (log.isTraceEnabled()) log.trace("try getResource " + name + " from " + _parent); tried_parent = true; url = _parent.getResource(name); } if (url == null) { if (log.isTraceEnabled()) log.trace("try findResource " + name + " from " + _urlClassPath); url = this.findResource(name); if (url == null && name.startsWith("/")) { if (log.isDebugEnabled()) log.debug("HACK leading / off " + name); url = this.findResource(name.substring(1)); } } if (_parent != null && url == null && !tried_parent) { if (log.isTraceEnabled()) log.trace("try getResource " + name + " from " + _parent); url = _parent.getResource(name); } if (url != null) if (log.isTraceEnabled()) log.trace("found " + url); return url; } /* ------------------------------------------------------------ */ public boolean isServerPath(String name) { name = name.replace('/', '.'); while (name.startsWith(".")) name = name.substring(1); String[] server_classes = _context.getServerClasses(); if (server_classes != null) { for (int i = 0; i < server_classes.length; i++) { boolean result = true; String c = server_classes[i]; if (c.startsWith("-")) { c = c.substring(1); result = false; } if (c.endsWith(".")) { if (name.startsWith(c)) return result; } else if (name.equals(c)) { return result; } } } return false; } /* ------------------------------------------------------------ */ public boolean isSystemPath(String name) { name = name.replace('/', '.'); while (name.startsWith(".")) name = name.substring(1); String[] system_classes = _context.getSystemClasses(); if (system_classes != null) { for (int i = 0; i < system_classes.length; i++) { boolean result = true; String c = system_classes[i]; if (c.startsWith("-")) { c = c.substring(1); result = false; } if (c.endsWith(".")) { if (name.startsWith(c)) return result; } else if (name.equals(c)) return result; } } return false; } /* ------------------------------------------------------------ */ public void destroy() { this._parent = null; this._permissions = null; this._urlClassPath = null; } /* ------------------------------------------------------------ */ /** * @return Returns the serverClasses. */ String[] getServerClasses() { return _context.getServerClasses(); } /* ------------------------------------------------------------ */ /** * @param serverClasses The serverClasses to set. */ void setServerClasses(String[] serverClasses) { _context.setServerClasses(serverClasses); } /* ------------------------------------------------------------ */ /** * @return Returns the systemClasses. */ String[] getSystemClasses() { return _context.getSystemClasses(); } /* ------------------------------------------------------------ */ /** * @param systemClasses The systemClasses to set. */ void setSystemClasses(String[] systemClasses) { _context.setSystemClasses(systemClasses); } }