103928aee4356845252ac6b662d5c72c29903813eJake Slack// 203928aee4356845252ac6b662d5c72c29903813eJake Slack// ======================================================================== 303928aee4356845252ac6b662d5c72c29903813eJake Slack// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. 403928aee4356845252ac6b662d5c72c29903813eJake Slack// ------------------------------------------------------------------------ 503928aee4356845252ac6b662d5c72c29903813eJake Slack// All rights reserved. This program and the accompanying materials 603928aee4356845252ac6b662d5c72c29903813eJake Slack// are made available under the terms of the Eclipse Public License v1.0 703928aee4356845252ac6b662d5c72c29903813eJake Slack// and Apache License v2.0 which accompanies this distribution. 803928aee4356845252ac6b662d5c72c29903813eJake Slack// 903928aee4356845252ac6b662d5c72c29903813eJake Slack// The Eclipse Public License is available at 1003928aee4356845252ac6b662d5c72c29903813eJake Slack// http://www.eclipse.org/legal/epl-v10.html 1103928aee4356845252ac6b662d5c72c29903813eJake Slack// 1203928aee4356845252ac6b662d5c72c29903813eJake Slack// The Apache License v2.0 is available at 1303928aee4356845252ac6b662d5c72c29903813eJake Slack// http://www.opensource.org/licenses/apache2.0.php 1403928aee4356845252ac6b662d5c72c29903813eJake Slack// 1503928aee4356845252ac6b662d5c72c29903813eJake Slack// You may elect to redistribute this code under either of these licenses. 1603928aee4356845252ac6b662d5c72c29903813eJake Slack// ======================================================================== 1703928aee4356845252ac6b662d5c72c29903813eJake Slack// 1803928aee4356845252ac6b662d5c72c29903813eJake Slack 1903928aee4356845252ac6b662d5c72c29903813eJake Slackpackage org.eclipse.jetty.webapp; 2003928aee4356845252ac6b662d5c72c29903813eJake Slack 2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.File; 2203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.IOException; 2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.net.URL; 2403928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.net.URLClassLoader; 2503928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.security.CodeSource; 2603928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.security.PermissionCollection; 2703928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.ArrayList; 2803928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Collections; 2903928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Enumeration; 3003928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.HashSet; 3103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.List; 3203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Locale; 3303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Set; 3403928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.StringTokenizer; 3503928aee4356845252ac6b662d5c72c29903813eJake Slack 3603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.StringUtil; 3703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Log; 3803928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Logger; 3903928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.resource.Resource; 4003928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.resource.ResourceCollection; 4103928aee4356845252ac6b662d5c72c29903813eJake Slack 4203928aee4356845252ac6b662d5c72c29903813eJake Slack 4303928aee4356845252ac6b662d5c72c29903813eJake Slack/* ------------------------------------------------------------ */ 4403928aee4356845252ac6b662d5c72c29903813eJake Slack/** ClassLoader for HttpContext. 4503928aee4356845252ac6b662d5c72c29903813eJake Slack * Specializes URLClassLoader with some utility and file mapping 4603928aee4356845252ac6b662d5c72c29903813eJake Slack * methods. 4703928aee4356845252ac6b662d5c72c29903813eJake Slack * 4803928aee4356845252ac6b662d5c72c29903813eJake Slack * This loader defaults to the 2.3 servlet spec behavior where non 4903928aee4356845252ac6b662d5c72c29903813eJake Slack * system classes are loaded from the classpath in preference to the 5003928aee4356845252ac6b662d5c72c29903813eJake Slack * parent loader. Java2 compliant loading, where the parent loader 5103928aee4356845252ac6b662d5c72c29903813eJake Slack * always has priority, can be selected with the 5203928aee4356845252ac6b662d5c72c29903813eJake Slack * {@link org.eclipse.jetty.webapp.WebAppContext#setParentLoaderPriority(boolean)} 5303928aee4356845252ac6b662d5c72c29903813eJake Slack * method and influenced with {@link WebAppContext#isServerClass(String)} and 5403928aee4356845252ac6b662d5c72c29903813eJake Slack * {@link WebAppContext#isSystemClass(String)}. 5503928aee4356845252ac6b662d5c72c29903813eJake Slack * 5603928aee4356845252ac6b662d5c72c29903813eJake Slack * If no parent class loader is provided, then the current thread 5703928aee4356845252ac6b662d5c72c29903813eJake Slack * context classloader will be used. If that is null then the 5803928aee4356845252ac6b662d5c72c29903813eJake Slack * classloader that loaded this class is used as the parent. 5903928aee4356845252ac6b662d5c72c29903813eJake Slack * 6003928aee4356845252ac6b662d5c72c29903813eJake Slack */ 6103928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class WebAppClassLoader extends URLClassLoader 6203928aee4356845252ac6b662d5c72c29903813eJake Slack{ 6303928aee4356845252ac6b662d5c72c29903813eJake Slack private static final Logger LOG = Log.getLogger(WebAppClassLoader.class); 6403928aee4356845252ac6b662d5c72c29903813eJake Slack 6503928aee4356845252ac6b662d5c72c29903813eJake Slack private final Context _context; 6603928aee4356845252ac6b662d5c72c29903813eJake Slack private final ClassLoader _parent; 6703928aee4356845252ac6b662d5c72c29903813eJake Slack private final Set<String> _extensions=new HashSet<String>(); 6803928aee4356845252ac6b662d5c72c29903813eJake Slack private String _name=String.valueOf(hashCode()); 6903928aee4356845252ac6b662d5c72c29903813eJake Slack 7003928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 7103928aee4356845252ac6b662d5c72c29903813eJake Slack /** The Context in which the classloader operates. 7203928aee4356845252ac6b662d5c72c29903813eJake Slack */ 7303928aee4356845252ac6b662d5c72c29903813eJake Slack public interface Context 7403928aee4356845252ac6b662d5c72c29903813eJake Slack { 7503928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 7603928aee4356845252ac6b662d5c72c29903813eJake Slack /** Convert a URL or path to a Resource. 7703928aee4356845252ac6b662d5c72c29903813eJake Slack * The default implementation 7803928aee4356845252ac6b662d5c72c29903813eJake Slack * is a wrapper for {@link Resource#newResource(String)}. 7903928aee4356845252ac6b662d5c72c29903813eJake Slack * @param urlOrPath The URL or path to convert 8003928aee4356845252ac6b662d5c72c29903813eJake Slack * @return The Resource for the URL/path 8103928aee4356845252ac6b662d5c72c29903813eJake Slack * @throws IOException The Resource could not be created. 8203928aee4356845252ac6b662d5c72c29903813eJake Slack */ 8303928aee4356845252ac6b662d5c72c29903813eJake Slack Resource newResource(String urlOrPath) throws IOException; 8403928aee4356845252ac6b662d5c72c29903813eJake Slack 8503928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 8603928aee4356845252ac6b662d5c72c29903813eJake Slack /** 8703928aee4356845252ac6b662d5c72c29903813eJake Slack * @return Returns the permissions. 8803928aee4356845252ac6b662d5c72c29903813eJake Slack */ 8903928aee4356845252ac6b662d5c72c29903813eJake Slack PermissionCollection getPermissions(); 9003928aee4356845252ac6b662d5c72c29903813eJake Slack 9103928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 9203928aee4356845252ac6b662d5c72c29903813eJake Slack /** Is the class a System Class. 9303928aee4356845252ac6b662d5c72c29903813eJake Slack * A System class is a class that is visible to a webapplication, 9403928aee4356845252ac6b662d5c72c29903813eJake Slack * but that cannot be overridden by the contents of WEB-INF/lib or 9503928aee4356845252ac6b662d5c72c29903813eJake Slack * WEB-INF/classes 9603928aee4356845252ac6b662d5c72c29903813eJake Slack * @param clazz The fully qualified name of the class. 9703928aee4356845252ac6b662d5c72c29903813eJake Slack * @return True if the class is a system class. 9803928aee4356845252ac6b662d5c72c29903813eJake Slack */ 9903928aee4356845252ac6b662d5c72c29903813eJake Slack boolean isSystemClass(String clazz); 10003928aee4356845252ac6b662d5c72c29903813eJake Slack 10103928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 10203928aee4356845252ac6b662d5c72c29903813eJake Slack /** Is the class a Server Class. 10303928aee4356845252ac6b662d5c72c29903813eJake Slack * A Server class is a class that is part of the implementation of 10403928aee4356845252ac6b662d5c72c29903813eJake Slack * the server and is NIT visible to a webapplication. The web 10503928aee4356845252ac6b662d5c72c29903813eJake Slack * application may provide it's own implementation of the class, 10603928aee4356845252ac6b662d5c72c29903813eJake Slack * to be loaded from WEB-INF/lib or WEB-INF/classes 10703928aee4356845252ac6b662d5c72c29903813eJake Slack * @param clazz The fully qualified name of the class. 10803928aee4356845252ac6b662d5c72c29903813eJake Slack * @return True if the class is a server class. 10903928aee4356845252ac6b662d5c72c29903813eJake Slack */ 11003928aee4356845252ac6b662d5c72c29903813eJake Slack boolean isServerClass(String clazz); 11103928aee4356845252ac6b662d5c72c29903813eJake Slack 11203928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 11303928aee4356845252ac6b662d5c72c29903813eJake Slack /** 11403928aee4356845252ac6b662d5c72c29903813eJake Slack * @return True if the classloader should delegate first to the parent 11503928aee4356845252ac6b662d5c72c29903813eJake Slack * classloader (standard java behaviour) or false if the classloader 11603928aee4356845252ac6b662d5c72c29903813eJake Slack * should first try to load from WEB-INF/lib or WEB-INF/classes (servlet 11703928aee4356845252ac6b662d5c72c29903813eJake Slack * spec recommendation). 11803928aee4356845252ac6b662d5c72c29903813eJake Slack */ 11903928aee4356845252ac6b662d5c72c29903813eJake Slack boolean isParentLoaderPriority(); 12003928aee4356845252ac6b662d5c72c29903813eJake Slack 12103928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 12203928aee4356845252ac6b662d5c72c29903813eJake Slack String getExtraClasspath(); 12303928aee4356845252ac6b662d5c72c29903813eJake Slack 12403928aee4356845252ac6b662d5c72c29903813eJake Slack } 12503928aee4356845252ac6b662d5c72c29903813eJake Slack 12603928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 12703928aee4356845252ac6b662d5c72c29903813eJake Slack /** Constructor. 12803928aee4356845252ac6b662d5c72c29903813eJake Slack */ 12903928aee4356845252ac6b662d5c72c29903813eJake Slack public WebAppClassLoader(Context context) 13003928aee4356845252ac6b662d5c72c29903813eJake Slack throws IOException 13103928aee4356845252ac6b662d5c72c29903813eJake Slack { 13203928aee4356845252ac6b662d5c72c29903813eJake Slack this(null,context); 13303928aee4356845252ac6b662d5c72c29903813eJake Slack } 13403928aee4356845252ac6b662d5c72c29903813eJake Slack 13503928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 13603928aee4356845252ac6b662d5c72c29903813eJake Slack /** Constructor. 13703928aee4356845252ac6b662d5c72c29903813eJake Slack */ 13803928aee4356845252ac6b662d5c72c29903813eJake Slack public WebAppClassLoader(ClassLoader parent, Context context) 13903928aee4356845252ac6b662d5c72c29903813eJake Slack throws IOException 14003928aee4356845252ac6b662d5c72c29903813eJake Slack { 14103928aee4356845252ac6b662d5c72c29903813eJake Slack super(new URL[]{},parent!=null?parent 14203928aee4356845252ac6b662d5c72c29903813eJake Slack :(Thread.currentThread().getContextClassLoader()!=null?Thread.currentThread().getContextClassLoader() 14303928aee4356845252ac6b662d5c72c29903813eJake Slack :(WebAppClassLoader.class.getClassLoader()!=null?WebAppClassLoader.class.getClassLoader() 14403928aee4356845252ac6b662d5c72c29903813eJake Slack :ClassLoader.getSystemClassLoader()))); 14503928aee4356845252ac6b662d5c72c29903813eJake Slack _parent=getParent(); 14603928aee4356845252ac6b662d5c72c29903813eJake Slack _context=context; 14703928aee4356845252ac6b662d5c72c29903813eJake Slack if (_parent==null) 14803928aee4356845252ac6b662d5c72c29903813eJake Slack throw new IllegalArgumentException("no parent classloader!"); 14903928aee4356845252ac6b662d5c72c29903813eJake Slack 15003928aee4356845252ac6b662d5c72c29903813eJake Slack _extensions.add(".jar"); 15103928aee4356845252ac6b662d5c72c29903813eJake Slack _extensions.add(".zip"); 15203928aee4356845252ac6b662d5c72c29903813eJake Slack 15303928aee4356845252ac6b662d5c72c29903813eJake Slack // TODO remove this system property 15403928aee4356845252ac6b662d5c72c29903813eJake Slack String extensions = System.getProperty(WebAppClassLoader.class.getName() + ".extensions"); 15503928aee4356845252ac6b662d5c72c29903813eJake Slack if(extensions!=null) 15603928aee4356845252ac6b662d5c72c29903813eJake Slack { 15703928aee4356845252ac6b662d5c72c29903813eJake Slack StringTokenizer tokenizer = new StringTokenizer(extensions, ",;"); 15803928aee4356845252ac6b662d5c72c29903813eJake Slack while(tokenizer.hasMoreTokens()) 15903928aee4356845252ac6b662d5c72c29903813eJake Slack _extensions.add(tokenizer.nextToken().trim()); 16003928aee4356845252ac6b662d5c72c29903813eJake Slack } 16103928aee4356845252ac6b662d5c72c29903813eJake Slack 16203928aee4356845252ac6b662d5c72c29903813eJake Slack if (context.getExtraClasspath()!=null) 16303928aee4356845252ac6b662d5c72c29903813eJake Slack addClassPath(context.getExtraClasspath()); 16403928aee4356845252ac6b662d5c72c29903813eJake Slack } 16503928aee4356845252ac6b662d5c72c29903813eJake Slack 16603928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 16703928aee4356845252ac6b662d5c72c29903813eJake Slack /** 16803928aee4356845252ac6b662d5c72c29903813eJake Slack * @return the name of the classloader 16903928aee4356845252ac6b662d5c72c29903813eJake Slack */ 17003928aee4356845252ac6b662d5c72c29903813eJake Slack public String getName() 17103928aee4356845252ac6b662d5c72c29903813eJake Slack { 17203928aee4356845252ac6b662d5c72c29903813eJake Slack return _name; 17303928aee4356845252ac6b662d5c72c29903813eJake Slack } 17403928aee4356845252ac6b662d5c72c29903813eJake Slack 17503928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 17603928aee4356845252ac6b662d5c72c29903813eJake Slack /** 17703928aee4356845252ac6b662d5c72c29903813eJake Slack * @param name the name of the classloader 17803928aee4356845252ac6b662d5c72c29903813eJake Slack */ 17903928aee4356845252ac6b662d5c72c29903813eJake Slack public void setName(String name) 18003928aee4356845252ac6b662d5c72c29903813eJake Slack { 18103928aee4356845252ac6b662d5c72c29903813eJake Slack _name=name; 18203928aee4356845252ac6b662d5c72c29903813eJake Slack } 18303928aee4356845252ac6b662d5c72c29903813eJake Slack 18403928aee4356845252ac6b662d5c72c29903813eJake Slack 18503928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 18603928aee4356845252ac6b662d5c72c29903813eJake Slack public Context getContext() 18703928aee4356845252ac6b662d5c72c29903813eJake Slack { 18803928aee4356845252ac6b662d5c72c29903813eJake Slack return _context; 18903928aee4356845252ac6b662d5c72c29903813eJake Slack } 19003928aee4356845252ac6b662d5c72c29903813eJake Slack 19103928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 19203928aee4356845252ac6b662d5c72c29903813eJake Slack /** 19303928aee4356845252ac6b662d5c72c29903813eJake Slack * @param resource Comma or semicolon separated path of filenames or URLs 19403928aee4356845252ac6b662d5c72c29903813eJake Slack * pointing to directories or jar files. Directories should end 19503928aee4356845252ac6b662d5c72c29903813eJake Slack * with '/'. 19603928aee4356845252ac6b662d5c72c29903813eJake Slack */ 19703928aee4356845252ac6b662d5c72c29903813eJake Slack public void addClassPath(Resource resource) 19803928aee4356845252ac6b662d5c72c29903813eJake Slack throws IOException 19903928aee4356845252ac6b662d5c72c29903813eJake Slack { 20003928aee4356845252ac6b662d5c72c29903813eJake Slack if (resource instanceof ResourceCollection) 20103928aee4356845252ac6b662d5c72c29903813eJake Slack { 20203928aee4356845252ac6b662d5c72c29903813eJake Slack for (Resource r : ((ResourceCollection)resource).getResources()) 20303928aee4356845252ac6b662d5c72c29903813eJake Slack addClassPath(r); 20403928aee4356845252ac6b662d5c72c29903813eJake Slack } 20503928aee4356845252ac6b662d5c72c29903813eJake Slack else 20603928aee4356845252ac6b662d5c72c29903813eJake Slack { 20703928aee4356845252ac6b662d5c72c29903813eJake Slack addClassPath(resource.toString()); 20803928aee4356845252ac6b662d5c72c29903813eJake Slack } 20903928aee4356845252ac6b662d5c72c29903813eJake Slack } 21003928aee4356845252ac6b662d5c72c29903813eJake Slack 21103928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 21203928aee4356845252ac6b662d5c72c29903813eJake Slack /** 21303928aee4356845252ac6b662d5c72c29903813eJake Slack * @param classPath Comma or semicolon separated path of filenames or URLs 21403928aee4356845252ac6b662d5c72c29903813eJake Slack * pointing to directories or jar files. Directories should end 21503928aee4356845252ac6b662d5c72c29903813eJake Slack * with '/'. 21603928aee4356845252ac6b662d5c72c29903813eJake Slack */ 21703928aee4356845252ac6b662d5c72c29903813eJake Slack public void addClassPath(String classPath) 21803928aee4356845252ac6b662d5c72c29903813eJake Slack throws IOException 21903928aee4356845252ac6b662d5c72c29903813eJake Slack { 22003928aee4356845252ac6b662d5c72c29903813eJake Slack if (classPath == null) 22103928aee4356845252ac6b662d5c72c29903813eJake Slack return; 22203928aee4356845252ac6b662d5c72c29903813eJake Slack 22303928aee4356845252ac6b662d5c72c29903813eJake Slack StringTokenizer tokenizer= new StringTokenizer(classPath, ",;"); 22403928aee4356845252ac6b662d5c72c29903813eJake Slack while (tokenizer.hasMoreTokens()) 22503928aee4356845252ac6b662d5c72c29903813eJake Slack { 22603928aee4356845252ac6b662d5c72c29903813eJake Slack Resource resource= _context.newResource(tokenizer.nextToken().trim()); 22703928aee4356845252ac6b662d5c72c29903813eJake Slack if (LOG.isDebugEnabled()) 22803928aee4356845252ac6b662d5c72c29903813eJake Slack LOG.debug("Path resource=" + resource); 22903928aee4356845252ac6b662d5c72c29903813eJake Slack 23003928aee4356845252ac6b662d5c72c29903813eJake Slack // Add the resource 23103928aee4356845252ac6b662d5c72c29903813eJake Slack if (resource.isDirectory() && resource instanceof ResourceCollection) 23203928aee4356845252ac6b662d5c72c29903813eJake Slack addClassPath(resource); 23303928aee4356845252ac6b662d5c72c29903813eJake Slack else 23403928aee4356845252ac6b662d5c72c29903813eJake Slack { 23503928aee4356845252ac6b662d5c72c29903813eJake Slack // Resolve file path if possible 23603928aee4356845252ac6b662d5c72c29903813eJake Slack File file= resource.getFile(); 23703928aee4356845252ac6b662d5c72c29903813eJake Slack if (file != null) 23803928aee4356845252ac6b662d5c72c29903813eJake Slack { 23903928aee4356845252ac6b662d5c72c29903813eJake Slack URL url= resource.getURL(); 24003928aee4356845252ac6b662d5c72c29903813eJake Slack addURL(url); 24103928aee4356845252ac6b662d5c72c29903813eJake Slack } 24203928aee4356845252ac6b662d5c72c29903813eJake Slack else if (resource.isDirectory()) 24303928aee4356845252ac6b662d5c72c29903813eJake Slack addURL(resource.getURL()); 24403928aee4356845252ac6b662d5c72c29903813eJake Slack else 24503928aee4356845252ac6b662d5c72c29903813eJake Slack throw new IllegalArgumentException("!file: "+resource); 24603928aee4356845252ac6b662d5c72c29903813eJake Slack } 24703928aee4356845252ac6b662d5c72c29903813eJake Slack } 24803928aee4356845252ac6b662d5c72c29903813eJake Slack } 24903928aee4356845252ac6b662d5c72c29903813eJake Slack 25003928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 25103928aee4356845252ac6b662d5c72c29903813eJake Slack /** 25203928aee4356845252ac6b662d5c72c29903813eJake Slack * @param file Checks if this file type can be added to the classpath. 25303928aee4356845252ac6b662d5c72c29903813eJake Slack */ 25403928aee4356845252ac6b662d5c72c29903813eJake Slack private boolean isFileSupported(String file) 25503928aee4356845252ac6b662d5c72c29903813eJake Slack { 25603928aee4356845252ac6b662d5c72c29903813eJake Slack int dot = file.lastIndexOf('.'); 25703928aee4356845252ac6b662d5c72c29903813eJake Slack return dot!=-1 && _extensions.contains(file.substring(dot)); 25803928aee4356845252ac6b662d5c72c29903813eJake Slack } 25903928aee4356845252ac6b662d5c72c29903813eJake Slack 26003928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 26103928aee4356845252ac6b662d5c72c29903813eJake Slack /** Add elements to the class path for the context from the jar and zip files found 26203928aee4356845252ac6b662d5c72c29903813eJake Slack * in the specified resource. 26303928aee4356845252ac6b662d5c72c29903813eJake Slack * @param lib the resource that contains the jar and/or zip files. 26403928aee4356845252ac6b662d5c72c29903813eJake Slack */ 26503928aee4356845252ac6b662d5c72c29903813eJake Slack public void addJars(Resource lib) 26603928aee4356845252ac6b662d5c72c29903813eJake Slack { 26703928aee4356845252ac6b662d5c72c29903813eJake Slack if (lib.exists() && lib.isDirectory()) 26803928aee4356845252ac6b662d5c72c29903813eJake Slack { 26903928aee4356845252ac6b662d5c72c29903813eJake Slack String[] files=lib.list(); 27003928aee4356845252ac6b662d5c72c29903813eJake Slack for (int f=0;files!=null && f<files.length;f++) 27103928aee4356845252ac6b662d5c72c29903813eJake Slack { 27203928aee4356845252ac6b662d5c72c29903813eJake Slack try 27303928aee4356845252ac6b662d5c72c29903813eJake Slack { 27403928aee4356845252ac6b662d5c72c29903813eJake Slack Resource fn=lib.addPath(files[f]); 27503928aee4356845252ac6b662d5c72c29903813eJake Slack String fnlc=fn.getName().toLowerCase(Locale.ENGLISH); 27603928aee4356845252ac6b662d5c72c29903813eJake Slack // don't check if this is a directory, see Bug 353165 27703928aee4356845252ac6b662d5c72c29903813eJake Slack if (isFileSupported(fnlc)) 27803928aee4356845252ac6b662d5c72c29903813eJake Slack { 27903928aee4356845252ac6b662d5c72c29903813eJake Slack String jar=fn.toString(); 28003928aee4356845252ac6b662d5c72c29903813eJake Slack jar=StringUtil.replace(jar, ",", "%2C"); 28103928aee4356845252ac6b662d5c72c29903813eJake Slack jar=StringUtil.replace(jar, ";", "%3B"); 28203928aee4356845252ac6b662d5c72c29903813eJake Slack addClassPath(jar); 28303928aee4356845252ac6b662d5c72c29903813eJake Slack } 28403928aee4356845252ac6b662d5c72c29903813eJake Slack } 28503928aee4356845252ac6b662d5c72c29903813eJake Slack catch (Exception ex) 28603928aee4356845252ac6b662d5c72c29903813eJake Slack { 28703928aee4356845252ac6b662d5c72c29903813eJake Slack LOG.warn(Log.EXCEPTION,ex); 28803928aee4356845252ac6b662d5c72c29903813eJake Slack } 28903928aee4356845252ac6b662d5c72c29903813eJake Slack } 29003928aee4356845252ac6b662d5c72c29903813eJake Slack } 29103928aee4356845252ac6b662d5c72c29903813eJake Slack } 29203928aee4356845252ac6b662d5c72c29903813eJake Slack 29303928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 29403928aee4356845252ac6b662d5c72c29903813eJake Slack public PermissionCollection getPermissions(CodeSource cs) 29503928aee4356845252ac6b662d5c72c29903813eJake Slack { 29603928aee4356845252ac6b662d5c72c29903813eJake Slack // TODO check CodeSource 29703928aee4356845252ac6b662d5c72c29903813eJake Slack PermissionCollection permissions=_context.getPermissions(); 29803928aee4356845252ac6b662d5c72c29903813eJake Slack PermissionCollection pc= (permissions == null) ? super.getPermissions(cs) : permissions; 29903928aee4356845252ac6b662d5c72c29903813eJake Slack return pc; 30003928aee4356845252ac6b662d5c72c29903813eJake Slack } 30103928aee4356845252ac6b662d5c72c29903813eJake Slack 30203928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 30303928aee4356845252ac6b662d5c72c29903813eJake Slack public Enumeration<URL> getResources(String name) throws IOException 30403928aee4356845252ac6b662d5c72c29903813eJake Slack { 30503928aee4356845252ac6b662d5c72c29903813eJake Slack boolean system_class=_context.isSystemClass(name); 30603928aee4356845252ac6b662d5c72c29903813eJake Slack boolean server_class=_context.isServerClass(name); 30703928aee4356845252ac6b662d5c72c29903813eJake Slack 30803928aee4356845252ac6b662d5c72c29903813eJake Slack List<URL> from_parent = toList(server_class?null:_parent.getResources(name)); 30903928aee4356845252ac6b662d5c72c29903813eJake Slack List<URL> from_webapp = toList((system_class&&!from_parent.isEmpty())?null:this.findResources(name)); 31003928aee4356845252ac6b662d5c72c29903813eJake Slack 31103928aee4356845252ac6b662d5c72c29903813eJake Slack if (_context.isParentLoaderPriority()) 31203928aee4356845252ac6b662d5c72c29903813eJake Slack { 31303928aee4356845252ac6b662d5c72c29903813eJake Slack from_parent.addAll(from_webapp); 31403928aee4356845252ac6b662d5c72c29903813eJake Slack return Collections.enumeration(from_parent); 31503928aee4356845252ac6b662d5c72c29903813eJake Slack } 31603928aee4356845252ac6b662d5c72c29903813eJake Slack from_webapp.addAll(from_parent); 31703928aee4356845252ac6b662d5c72c29903813eJake Slack return Collections.enumeration(from_webapp); 31803928aee4356845252ac6b662d5c72c29903813eJake Slack } 31903928aee4356845252ac6b662d5c72c29903813eJake Slack 32003928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 32103928aee4356845252ac6b662d5c72c29903813eJake Slack private List<URL> toList(Enumeration<URL> e) 32203928aee4356845252ac6b662d5c72c29903813eJake Slack { 32303928aee4356845252ac6b662d5c72c29903813eJake Slack if (e==null) 32403928aee4356845252ac6b662d5c72c29903813eJake Slack return new ArrayList<URL>(); 32503928aee4356845252ac6b662d5c72c29903813eJake Slack return Collections.list(e); 32603928aee4356845252ac6b662d5c72c29903813eJake Slack } 32703928aee4356845252ac6b662d5c72c29903813eJake Slack 32803928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 32903928aee4356845252ac6b662d5c72c29903813eJake Slack /** 33003928aee4356845252ac6b662d5c72c29903813eJake Slack * Get a resource from the classloader 33103928aee4356845252ac6b662d5c72c29903813eJake Slack * 33203928aee4356845252ac6b662d5c72c29903813eJake Slack * NOTE: this method provides a convenience of hacking off a leading / 33303928aee4356845252ac6b662d5c72c29903813eJake Slack * should one be present. This is non-standard and it is recommended 33403928aee4356845252ac6b662d5c72c29903813eJake Slack * to not rely on this behavior 33503928aee4356845252ac6b662d5c72c29903813eJake Slack */ 33603928aee4356845252ac6b662d5c72c29903813eJake Slack public URL getResource(String name) 33703928aee4356845252ac6b662d5c72c29903813eJake Slack { 33803928aee4356845252ac6b662d5c72c29903813eJake Slack URL url= null; 33903928aee4356845252ac6b662d5c72c29903813eJake Slack boolean tried_parent= false; 34003928aee4356845252ac6b662d5c72c29903813eJake Slack boolean system_class=_context.isSystemClass(name); 34103928aee4356845252ac6b662d5c72c29903813eJake Slack boolean server_class=_context.isServerClass(name); 34203928aee4356845252ac6b662d5c72c29903813eJake Slack 34303928aee4356845252ac6b662d5c72c29903813eJake Slack if (system_class && server_class) 34403928aee4356845252ac6b662d5c72c29903813eJake Slack return null; 34503928aee4356845252ac6b662d5c72c29903813eJake Slack 34603928aee4356845252ac6b662d5c72c29903813eJake Slack if (_parent!=null &&(_context.isParentLoaderPriority() || system_class ) && !server_class) 34703928aee4356845252ac6b662d5c72c29903813eJake Slack { 34803928aee4356845252ac6b662d5c72c29903813eJake Slack tried_parent= true; 34903928aee4356845252ac6b662d5c72c29903813eJake Slack 35003928aee4356845252ac6b662d5c72c29903813eJake Slack if (_parent!=null) 35103928aee4356845252ac6b662d5c72c29903813eJake Slack url= _parent.getResource(name); 35203928aee4356845252ac6b662d5c72c29903813eJake Slack } 35303928aee4356845252ac6b662d5c72c29903813eJake Slack 35403928aee4356845252ac6b662d5c72c29903813eJake Slack if (url == null) 35503928aee4356845252ac6b662d5c72c29903813eJake Slack { 35603928aee4356845252ac6b662d5c72c29903813eJake Slack url= this.findResource(name); 35703928aee4356845252ac6b662d5c72c29903813eJake Slack 35803928aee4356845252ac6b662d5c72c29903813eJake Slack if (url == null && name.startsWith("/")) 35903928aee4356845252ac6b662d5c72c29903813eJake Slack { 36003928aee4356845252ac6b662d5c72c29903813eJake Slack if (LOG.isDebugEnabled()) 36103928aee4356845252ac6b662d5c72c29903813eJake Slack LOG.debug("HACK leading / off " + name); 36203928aee4356845252ac6b662d5c72c29903813eJake Slack url= this.findResource(name.substring(1)); 36303928aee4356845252ac6b662d5c72c29903813eJake Slack } 36403928aee4356845252ac6b662d5c72c29903813eJake Slack } 36503928aee4356845252ac6b662d5c72c29903813eJake Slack 36603928aee4356845252ac6b662d5c72c29903813eJake Slack if (url == null && !tried_parent && !server_class ) 36703928aee4356845252ac6b662d5c72c29903813eJake Slack { 36803928aee4356845252ac6b662d5c72c29903813eJake Slack if (_parent!=null) 36903928aee4356845252ac6b662d5c72c29903813eJake Slack url= _parent.getResource(name); 37003928aee4356845252ac6b662d5c72c29903813eJake Slack } 37103928aee4356845252ac6b662d5c72c29903813eJake Slack 37203928aee4356845252ac6b662d5c72c29903813eJake Slack if (url != null) 37303928aee4356845252ac6b662d5c72c29903813eJake Slack if (LOG.isDebugEnabled()) 37403928aee4356845252ac6b662d5c72c29903813eJake Slack LOG.debug("getResource("+name+")=" + url); 37503928aee4356845252ac6b662d5c72c29903813eJake Slack 37603928aee4356845252ac6b662d5c72c29903813eJake Slack return url; 37703928aee4356845252ac6b662d5c72c29903813eJake Slack } 37803928aee4356845252ac6b662d5c72c29903813eJake Slack 37903928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 38003928aee4356845252ac6b662d5c72c29903813eJake Slack @Override 38103928aee4356845252ac6b662d5c72c29903813eJake Slack public Class<?> loadClass(String name) throws ClassNotFoundException 38203928aee4356845252ac6b662d5c72c29903813eJake Slack { 38303928aee4356845252ac6b662d5c72c29903813eJake Slack return loadClass(name, false); 38403928aee4356845252ac6b662d5c72c29903813eJake Slack } 38503928aee4356845252ac6b662d5c72c29903813eJake Slack 38603928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 38703928aee4356845252ac6b662d5c72c29903813eJake Slack @Override 38803928aee4356845252ac6b662d5c72c29903813eJake Slack protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException 38903928aee4356845252ac6b662d5c72c29903813eJake Slack { 39003928aee4356845252ac6b662d5c72c29903813eJake Slack Class<?> c= findLoadedClass(name); 39103928aee4356845252ac6b662d5c72c29903813eJake Slack ClassNotFoundException ex= null; 39203928aee4356845252ac6b662d5c72c29903813eJake Slack boolean tried_parent= false; 39303928aee4356845252ac6b662d5c72c29903813eJake Slack 39403928aee4356845252ac6b662d5c72c29903813eJake Slack boolean system_class=_context.isSystemClass(name); 39503928aee4356845252ac6b662d5c72c29903813eJake Slack boolean server_class=_context.isServerClass(name); 39603928aee4356845252ac6b662d5c72c29903813eJake Slack 39703928aee4356845252ac6b662d5c72c29903813eJake Slack if (system_class && server_class) 39803928aee4356845252ac6b662d5c72c29903813eJake Slack { 39903928aee4356845252ac6b662d5c72c29903813eJake Slack return null; 40003928aee4356845252ac6b662d5c72c29903813eJake Slack } 40103928aee4356845252ac6b662d5c72c29903813eJake Slack 40203928aee4356845252ac6b662d5c72c29903813eJake Slack if (c == null && _parent!=null && (_context.isParentLoaderPriority() || system_class) && !server_class) 40303928aee4356845252ac6b662d5c72c29903813eJake Slack { 40403928aee4356845252ac6b662d5c72c29903813eJake Slack tried_parent= true; 40503928aee4356845252ac6b662d5c72c29903813eJake Slack try 40603928aee4356845252ac6b662d5c72c29903813eJake Slack { 40703928aee4356845252ac6b662d5c72c29903813eJake Slack c= _parent.loadClass(name); 40803928aee4356845252ac6b662d5c72c29903813eJake Slack if (LOG.isDebugEnabled()) 40903928aee4356845252ac6b662d5c72c29903813eJake Slack LOG.debug("loaded " + c); 41003928aee4356845252ac6b662d5c72c29903813eJake Slack } 41103928aee4356845252ac6b662d5c72c29903813eJake Slack catch (ClassNotFoundException e) 41203928aee4356845252ac6b662d5c72c29903813eJake Slack { 41303928aee4356845252ac6b662d5c72c29903813eJake Slack ex= e; 41403928aee4356845252ac6b662d5c72c29903813eJake Slack } 41503928aee4356845252ac6b662d5c72c29903813eJake Slack } 41603928aee4356845252ac6b662d5c72c29903813eJake Slack 41703928aee4356845252ac6b662d5c72c29903813eJake Slack if (c == null) 41803928aee4356845252ac6b662d5c72c29903813eJake Slack { 41903928aee4356845252ac6b662d5c72c29903813eJake Slack try 42003928aee4356845252ac6b662d5c72c29903813eJake Slack { 42103928aee4356845252ac6b662d5c72c29903813eJake Slack c= this.findClass(name); 42203928aee4356845252ac6b662d5c72c29903813eJake Slack } 42303928aee4356845252ac6b662d5c72c29903813eJake Slack catch (ClassNotFoundException e) 42403928aee4356845252ac6b662d5c72c29903813eJake Slack { 42503928aee4356845252ac6b662d5c72c29903813eJake Slack ex= e; 42603928aee4356845252ac6b662d5c72c29903813eJake Slack } 42703928aee4356845252ac6b662d5c72c29903813eJake Slack } 42803928aee4356845252ac6b662d5c72c29903813eJake Slack 42903928aee4356845252ac6b662d5c72c29903813eJake Slack if (c == null && _parent!=null && !tried_parent && !server_class ) 43003928aee4356845252ac6b662d5c72c29903813eJake Slack c= _parent.loadClass(name); 43103928aee4356845252ac6b662d5c72c29903813eJake Slack 43203928aee4356845252ac6b662d5c72c29903813eJake Slack if (c == null) 43303928aee4356845252ac6b662d5c72c29903813eJake Slack throw ex; 43403928aee4356845252ac6b662d5c72c29903813eJake Slack 43503928aee4356845252ac6b662d5c72c29903813eJake Slack if (resolve) 43603928aee4356845252ac6b662d5c72c29903813eJake Slack resolveClass(c); 43703928aee4356845252ac6b662d5c72c29903813eJake Slack 43803928aee4356845252ac6b662d5c72c29903813eJake Slack if (LOG.isDebugEnabled()) 43903928aee4356845252ac6b662d5c72c29903813eJake Slack LOG.debug("loaded " + c+ " from "+c.getClassLoader()); 44003928aee4356845252ac6b662d5c72c29903813eJake Slack 44103928aee4356845252ac6b662d5c72c29903813eJake Slack return c; 44203928aee4356845252ac6b662d5c72c29903813eJake Slack } 44303928aee4356845252ac6b662d5c72c29903813eJake Slack 44403928aee4356845252ac6b662d5c72c29903813eJake Slack /* ------------------------------------------------------------ */ 44503928aee4356845252ac6b662d5c72c29903813eJake Slack public String toString() 44603928aee4356845252ac6b662d5c72c29903813eJake Slack { 44703928aee4356845252ac6b662d5c72c29903813eJake Slack return "WebAppClassLoader=" + _name+"@"+Long.toHexString(hashCode()); 44803928aee4356845252ac6b662d5c72c29903813eJake Slack } 44903928aee4356845252ac6b662d5c72c29903813eJake Slack} 450