Fixes issue #1032; fixes a bug in Tomcat that prevents it from embedding properly. It was kicking directly to the system classloader instead of following the proper chain of command.
Removed the need to override WebappLoader, as we've done from time immemorial.
git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/1.6@4511 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/shell/tomcat/EmbeddedTomcatServer.java b/dev/core/src/com/google/gwt/dev/shell/tomcat/EmbeddedTomcatServer.java
index 1fc2d9b..0bccea5 100644
--- a/dev/core/src/com/google/gwt/dev/shell/tomcat/EmbeddedTomcatServer.java
+++ b/dev/core/src/com/google/gwt/dev/shell/tomcat/EmbeddedTomcatServer.java
@@ -203,6 +203,7 @@
catEngine = catEmbedded.createEngine();
catEngine.setName("gwt");
catEngine.setDefaultHost("localhost");
+ catEngine.setParentClassLoader(this.getClass().getClassLoader());
// It answers localhost requests.
//
@@ -363,7 +364,7 @@
*/
private Map<String, Resource> getResourcesFor(TreeLogger logger,
String tomcatEtcDir) throws URISyntaxException, IOException {
- ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+ ClassLoader contextClassLoader = this.getClass().getClassLoader();
URL url = contextClassLoader.getResource(tomcatEtcDir);
if (url == null) {
return null;
diff --git a/dev/core/src/org/apache/catalina/loader/WebappClassLoader.java b/dev/core/src/org/apache/catalina/loader/WebappClassLoader.java
index 465fbb0..f9c5ee0 100644
--- a/dev/core/src/org/apache/catalina/loader/WebappClassLoader.java
+++ b/dev/core/src/org/apache/catalina/loader/WebappClassLoader.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
+// Modified by Google.
package org.apache.catalina.loader;
@@ -731,10 +731,10 @@
if (getJarPath() != null) {
try {
- NamingEnumeration enum = resources.listBindings(getJarPath());
+ NamingEnumeration enum_ = resources.listBindings(getJarPath());
int i = 0;
- while (enum.hasMoreElements() && (i < length)) {
- NameClassPair ncPair = (NameClassPair) enum.nextElement();
+ while (enum_.hasMoreElements() && (i < length)) {
+ NameClassPair ncPair = (NameClassPair) enum_.nextElement();
String name = ncPair.getName();
// Ignore non JARs present in the lib folder
if (!name.endsWith(".jar"))
@@ -747,10 +747,10 @@
}
i++;
}
- if (enum.hasMoreElements()) {
- while (enum.hasMoreElements()) {
+ if (enum_.hasMoreElements()) {
+ while (enum_.hasMoreElements()) {
NameClassPair ncPair =
- (NameClassPair) enum.nextElement();
+ (NameClassPair) enum_.nextElement();
String name = ncPair.getName();
// Additional non-JAR files are allowed
if (name.endsWith(".jar")) {
@@ -1251,13 +1251,16 @@
// (0.2) Try loading the class with the system class loader, to prevent
// the webapp from overriding J2SE classes
+ // GOOGLE: use the bootstrap loader, not the system loader; it breaks
+ // embedding.
try {
- clazz = system.loadClass(name);
- if (clazz != null) {
- if (resolve)
- resolveClass(clazz);
- return (clazz);
- }
+ // clazz = system.loadClass(name);
+ clazz = Class.forName(name, false, null);
+ if (clazz != null) {
+ if (resolve)
+ resolveClass(clazz);
+ return (clazz);
+ }
} catch (ClassNotFoundException e) {
// Ignore
}
@@ -2162,4 +2165,3 @@
}
}
-
diff --git a/dev/core/src/org/apache/catalina/loader/WebappLoader.java b/dev/core/src/org/apache/catalina/loader/WebappLoader.java
deleted file mode 100644
index a38aeba..0000000
--- a/dev/core/src/org/apache/catalina/loader/WebappLoader.java
+++ /dev/null
@@ -1,1238 +0,0 @@
-/*
- * Copyright 1999,2004 The Apache Software Foundation.
- *
- * 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.
- */
-// Modified by Google
-package org.apache.catalina.loader;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FilePermission;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.net.URLStreamHandlerFactory;
-import java.util.ArrayList;
-import java.util.jar.JarFile;
-
-import javax.management.MBeanRegistration;
-import javax.management.MBeanServer;
-import javax.management.ObjectName;
-import javax.naming.Binding;
-import javax.naming.NameClassPair;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.directory.DirContext;
-import javax.servlet.ServletContext;
-
-import org.apache.catalina.Container;
-import org.apache.catalina.Context;
-import org.apache.catalina.DefaultContext;
-import org.apache.catalina.Engine;
-import org.apache.catalina.Globals;
-import org.apache.catalina.Lifecycle;
-import org.apache.catalina.LifecycleException;
-import org.apache.catalina.LifecycleListener;
-import org.apache.catalina.Loader;
-import org.apache.catalina.Logger;
-import org.apache.catalina.core.StandardContext;
-import org.apache.catalina.util.LifecycleSupport;
-import org.apache.catalina.util.StringManager;
-import org.apache.commons.modeler.Registry;
-import org.apache.naming.resources.DirContextURLStreamHandler;
-import org.apache.naming.resources.DirContextURLStreamHandlerFactory;
-import org.apache.naming.resources.Resource;
-
-/**
- * Classloader implementation which is specialized for handling web applications
- * in the most efficient way, while being Catalina aware (all accesses to
- * resources are made through the DirContext interface). This class loader
- * supports detection of modified Java classes, which can be used to implement
- * auto-reload support.
- * <p>
- * This class loader is configured by adding the pathnames of directories, JAR
- * files, and ZIP files with the <code>addRepository()</code> method, prior to
- * calling <code>start()</code>. When a new class is required, these
- * repositories will be consulted first to locate the class. If it is not
- * present, the system class loader will be used instead.
- *
- * @author Craig R. McClanahan
- * @author Remy Maucherat
- * @version $Revision: 1.27 $ $Date: 2004/03/02 12:31:57 $
- */
-
-public class WebappLoader implements Lifecycle, Loader, PropertyChangeListener,
- MBeanRegistration {
-
- // ----------------------------------------------------------- Constructors
-
- /**
- * Construct a new WebappLoader with no defined parent class loader (so that
- * the actual parent will be the system class loader).
- */
- public WebappLoader() {
-
- this(null);
-
- }
-
- /**
- * Construct a new WebappLoader with the specified class loader to be defined
- * as the parent of the ClassLoader we ultimately create.
- *
- * @param parent The parent class loader
- */
- public WebappLoader(ClassLoader parent) {
- super();
- this.parentClassLoader = parent;
- }
-
- // ----------------------------------------------------- Instance Variables
-
- /**
- * First load of the class.
- */
- private static boolean first = true;
-
- /**
- * The class loader being managed by this Loader component.
- */
- private WebappClassLoader classLoader = null;
-
- /**
- * The Container with which this Loader has been associated.
- */
- private Container container = null;
-
- /**
- * The debugging detail level for this component.
- */
- private int debug = 0;
-
- /**
- * The DefaultContext with which this Loader is associated.
- */
- protected DefaultContext defaultContext = null;
-
- /**
- * The "follow standard delegation model" flag that will be used to configure
- * our ClassLoader.
- */
- private boolean delegate = false;
-
- /**
- * The descriptive information about this Loader implementation.
- */
- private static final String info = "org.apache.catalina.loader.WebappLoader/1.0";
-
- /**
- * The lifecycle event support for this component.
- */
- protected LifecycleSupport lifecycle = new LifecycleSupport(this);
-
- /**
- * The Java class name of the ClassLoader implementation to be used. This
- * class should extend WebappClassLoader, otherwise, a different loader
- * implementation must be used.
- */
- private String loaderClass = "org.apache.catalina.loader.WebappClassLoader";
-
- /**
- * The parent class loader of the class loader we will create.
- */
- private ClassLoader parentClassLoader = null;
-
- /**
- * The reloadable flag for this Loader.
- */
- private boolean reloadable = false;
-
- /**
- * The set of repositories associated with this class loader.
- */
- private String repositories[] = new String[0];
-
- /**
- * The string manager for this package.
- */
- protected static final StringManager sm = StringManager.getManager(Constants.Package);
-
- /**
- * Has this component been started?
- */
- private boolean started = false;
-
- /**
- * The property change support for this component.
- */
- protected PropertyChangeSupport support = new PropertyChangeSupport(this);
-
- /**
- * Classpath set in the loader.
- */
- private String classpath = null;
-
- /**
- * Repositories that are set in the loader, for JMX. GOOGLE: Added type
- * information.
- */
- private ArrayList<String> loaderRepositories = null;
-
- // ------------------------------------------------------------- Properties
-
- /**
- * Return the Java class loader to be used by this Container.
- */
- public ClassLoader getClassLoader() {
-
- /*
- * GOOGLE: When tomcat is embedded (as we are doing), classLoader is always
- * null. Returning the parentClassLoader seems to do the right thing.
- */
- if (classLoader != null) {
- return classLoader;
- } else {
- return parentClassLoader;
- }
-
- }
-
- /**
- * Return the Container with which this Logger has been associated.
- */
- public Container getContainer() {
-
- return (container);
-
- }
-
- /**
- * Set the Container with which this Logger has been associated.
- *
- * @param container The associated Container
- */
- public void setContainer(Container container) {
-
- // Deregister from the old Container (if any)
- if ((this.container != null) && (this.container instanceof Context))
- ((Context) this.container).removePropertyChangeListener(this);
-
- // Process this property change
- Container oldContainer = this.container;
- this.container = container;
- support.firePropertyChange("container", oldContainer, this.container);
-
- // Register with the new Container (if any)
- if ((this.container != null) && (this.container instanceof Context)) {
- setReloadable(((Context) this.container).getReloadable());
- ((Context) this.container).addPropertyChangeListener(this);
- }
-
- }
-
- /**
- * Return the DefaultContext with which this Loader is associated. XXX What is
- * that ???
- */
- public DefaultContext getDefaultContext() {
-
- return (this.defaultContext);
-
- }
-
- /**
- * Set the DefaultContext with which this Loader is associated.
- *
- * @param defaultContext The newly associated DefaultContext
- */
- public void setDefaultContext(DefaultContext defaultContext) {
-
- DefaultContext oldDefaultContext = this.defaultContext;
- this.defaultContext = defaultContext;
- support.firePropertyChange("defaultContext", oldDefaultContext,
- this.defaultContext);
-
- }
-
- /**
- * Return the debugging detail level for this component.
- */
- public int getDebug() {
-
- return (this.debug);
-
- }
-
- /**
- * Set the debugging detail level for this component.
- *
- * @param debug The new debugging detail level
- */
- public void setDebug(int debug) {
-
- int oldDebug = this.debug;
- this.debug = debug;
- support.firePropertyChange("debug", new Integer(oldDebug), new Integer(
- this.debug));
-
- }
-
- /**
- * Return the "follow standard delegation model" flag used to configure our
- * ClassLoader.
- */
- public boolean getDelegate() {
-
- return (this.delegate);
-
- }
-
- /**
- * Set the "follow standard delegation model" flag used to configure our
- * ClassLoader.
- *
- * @param delegate The new flag
- */
- public void setDelegate(boolean delegate) {
-
- boolean oldDelegate = this.delegate;
- this.delegate = delegate;
- support.firePropertyChange("delegate", new Boolean(oldDelegate),
- new Boolean(this.delegate));
-
- }
-
- /**
- * Return descriptive information about this Loader implementation and the
- * corresponding version number, in the format
- * <code><description>/<version></code>.
- */
- public String getInfo() {
-
- return (info);
-
- }
-
- /**
- * Return the ClassLoader class name.
- */
- public String getLoaderClass() {
-
- return (this.loaderClass);
-
- }
-
- /**
- * Set the ClassLoader class name.
- *
- * @param loaderClass The new ClassLoader class name
- */
- public void setLoaderClass(String loaderClass) {
-
- this.loaderClass = loaderClass;
-
- }
-
- /**
- * Return the reloadable flag for this Loader.
- */
- public boolean getReloadable() {
-
- return (this.reloadable);
-
- }
-
- /**
- * Set the reloadable flag for this Loader.
- *
- * @param reloadable The new reloadable flag
- */
- public void setReloadable(boolean reloadable) {
-
- // Process this property change
- boolean oldReloadable = this.reloadable;
- this.reloadable = reloadable;
- support.firePropertyChange("reloadable", new Boolean(oldReloadable),
- new Boolean(this.reloadable));
-
- }
-
- // --------------------------------------------------------- Public Methods
-
- /**
- * Add a property change listener to this component.
- *
- * @param listener The listener to add
- */
- public void addPropertyChangeListener(PropertyChangeListener listener) {
-
- support.addPropertyChangeListener(listener);
-
- }
-
- /**
- * Add a new repository to the set of repositories for this class loader.
- *
- * @param repository Repository to be added
- */
- public void addRepository(String repository) {
-
- if (log.isDebugEnabled())
- log.debug(sm.getString("webappLoader.addRepository", repository));
-
- for (int i = 0; i < repositories.length; i++) {
- if (repository.equals(repositories[i]))
- return;
- }
- String results[] = new String[repositories.length + 1];
- for (int i = 0; i < repositories.length; i++)
- results[i] = repositories[i];
- results[repositories.length] = repository;
- repositories = results;
-
- if (started && (classLoader != null)) {
- classLoader.addRepository(repository);
- if (loaderRepositories != null)
- loaderRepositories.add(repository);
- setClassPath();
- }
-
- }
-
- /**
- * Return the set of repositories defined for this class loader. If none are
- * defined, a zero-length array is returned. For security reason, returns a
- * clone of the Array (since String are immutable).
- */
- public String[] findRepositories() {
-
- return ((String[]) repositories.clone());
-
- }
-
- public String[] getRepositories() {
- return ((String[]) repositories.clone());
- }
-
- /**
- * Extra repositories for this loader
- */
- public String getRepositoriesString() {
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < repositories.length; i++) {
- sb.append(repositories[i]).append(":");
- }
- return sb.toString();
- }
-
- public String[] getLoaderRepositories() {
- if (loaderRepositories == null)
- return null;
- String res[] = new String[loaderRepositories.size()];
- loaderRepositories.toArray(res);
- return res;
- }
-
- public String getLoaderRepositoriesString() {
- String repositories[] = getLoaderRepositories();
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < repositories.length; i++) {
- sb.append(repositories[i]).append(":");
- }
- return sb.toString();
- }
-
- /**
- * Classpath, as set in org.apache.catalina.jsp_classpath context property
- *
- * @return The classpath
- */
- public String getClasspath() {
- return classpath;
- }
-
- /**
- * Has the internal repository associated with this Loader been modified, such
- * that the loaded classes should be reloaded?
- */
- public boolean modified() {
-
- return (classLoader.modified());
-
- }
-
- /**
- * Used to periodically signal to the classloader to release JAR resources.
- */
- public void closeJARs(boolean force) {
- if (classLoader != null) {
- classLoader.closeJARs(force);
- }
- }
-
- /**
- * Remove a property change listener from this component.
- *
- * @param listener The listener to remove
- */
- public void removePropertyChangeListener(PropertyChangeListener listener) {
-
- support.removePropertyChangeListener(listener);
-
- }
-
- /**
- * Return a String representation of this component.
- */
- public String toString() {
-
- StringBuffer sb = new StringBuffer("WebappLoader[");
- if (container != null)
- sb.append(container.getName());
- sb.append("]");
- return (sb.toString());
-
- }
-
- // ------------------------------------------------------ Lifecycle Methods
-
- /**
- * Add a lifecycle event listener to this component.
- *
- * @param listener The listener to add
- */
- public void addLifecycleListener(LifecycleListener listener) {
-
- lifecycle.addLifecycleListener(listener);
-
- }
-
- /**
- * Get the lifecycle listeners associated with this lifecycle. If this
- * Lifecycle has no listeners registered, a zero-length array is returned.
- */
- public LifecycleListener[] findLifecycleListeners() {
-
- return lifecycle.findLifecycleListeners();
-
- }
-
- /**
- * Remove a lifecycle event listener from this component.
- *
- * @param listener The listener to remove
- */
- public void removeLifecycleListener(LifecycleListener listener) {
-
- lifecycle.removeLifecycleListener(listener);
-
- }
-
- private boolean initialized = false;
-
- public void init() {
- initialized = true;
-
- if (oname == null) {
- // not registered yet - standalone or API
- if (container instanceof StandardContext) {
- // Register ourself. The container must be a webapp
- try {
- StandardContext ctx = (StandardContext) container;
- Engine eng = (Engine) ctx.getParent().getParent();
- String path = ctx.getPath();
- if (path.equals("")) {
- path = "/";
- }
- oname = new ObjectName(ctx.getEngineName() + ":type=Loader,path="
- + path + ",host=" + ctx.getParent().getName());
- Registry.getRegistry(null, null).registerComponent(this, oname, null);
- controller = oname;
- } catch (Exception e) {
- log.error("Error registering loader", e);
- }
- }
- }
-
- if (container == null) {
- // JMX created the loader
- // TODO
-
- }
- }
-
- public void destroy() {
- if (controller == oname) {
- // Self-registration, undo it
- Registry.getRegistry(null, null).unregisterComponent(oname);
- oname = null;
- }
- initialized = false;
-
- }
-
- /**
- * Start this component, initializing our associated class loader.
- *
- * @exception LifecycleException if a lifecycle error occurs
- */
- public void start() throws LifecycleException {
- // Validate and update our current component state
- if (!initialized)
- init();
- if (started)
- throw new LifecycleException(sm.getString("webappLoader.alreadyStarted"));
- if (log.isDebugEnabled())
- log.debug(sm.getString("webappLoader.starting"));
- lifecycle.fireLifecycleEvent(START_EVENT, null);
- started = true;
-
- if (container.getResources() == null) {
- log.info("No resources for " + container);
- return;
- }
- // Register a stream handler factory for the JNDI protocol
- URLStreamHandlerFactory streamHandlerFactory = new DirContextURLStreamHandlerFactory();
- if (first) {
- first = false;
- try {
- URL.setURLStreamHandlerFactory(streamHandlerFactory);
- } catch (Exception e) {
- // Log and continue anyway, this is not critical
- log.error("Error registering jndi stream handler", e);
- } catch (Throwable t) {
- // This is likely a dual registration
- log.info("Dual registration of jndi stream handler: " + t.getMessage());
- }
- }
-
- // Construct a class loader based on our current repositories list
- try {
-
- classLoader = createClassLoader();
- classLoader.setResources(container.getResources());
- classLoader.setDebug(this.debug);
- classLoader.setDelegate(this.delegate);
-
- for (int i = 0; i < repositories.length; i++) {
- classLoader.addRepository(repositories[i]);
- }
-
- // Configure our repositories
- setRepositories();
- setClassPath();
-
- setPermissions();
-
- if (classLoader instanceof Lifecycle)
- ((Lifecycle) classLoader).start();
-
- // Binding the Webapp class loader to the directory context
- DirContextURLStreamHandler.bind((ClassLoader) classLoader,
- this.container.getResources());
-
- StandardContext ctx = (StandardContext) container;
- Engine eng = (Engine) ctx.getParent().getParent();
- String path = ctx.getPath();
- if (path.equals("")) {
- path = "/";
- }
- ObjectName cloname = new ObjectName(ctx.getEngineName()
- + ":type=WebappClassLoader,path=" + path + ",host="
- + ctx.getParent().getName());
- Registry.getRegistry(null, null).registerComponent(classLoader, cloname,
- null);
-
- } catch (Throwable t) {
- log.error("LifecycleException ", t);
- throw new LifecycleException("start: ", t);
- }
-
- }
-
- /**
- * Stop this component, finalizing our associated class loader.
- *
- * @exception LifecycleException if a lifecycle error occurs
- */
- public void stop() throws LifecycleException {
-
- // Validate and update our current component state
- if (!started)
- throw new LifecycleException(sm.getString("webappLoader.notStarted"));
- if (log.isDebugEnabled())
- log.debug(sm.getString("webappLoader.stopping"));
- lifecycle.fireLifecycleEvent(STOP_EVENT, null);
- started = false;
-
- // Remove context attributes as appropriate
- if (container instanceof Context) {
- ServletContext servletContext = ((Context) container).getServletContext();
- servletContext.removeAttribute(Globals.CLASS_PATH_ATTR);
- }
-
- // Throw away our current class loader
- if (classLoader instanceof Lifecycle)
- ((Lifecycle) classLoader).stop();
- DirContextURLStreamHandler.unbind((ClassLoader) classLoader);
-
- try {
- StandardContext ctx = (StandardContext) container;
- Engine eng = (Engine) ctx.getParent().getParent();
- String path = ctx.getPath();
- if (path.equals("")) {
- path = "/";
- }
- ObjectName cloname = new ObjectName(ctx.getEngineName()
- + ":type=WebappClassLoader,path=" + path + ",host="
- + ctx.getParent().getName());
- Registry.getRegistry(null, null).unregisterComponent(cloname);
- } catch (Throwable t) {
- log.error("LifecycleException ", t);
- }
-
- classLoader = null;
-
- destroy();
-
- }
-
- // ----------------------------------------- PropertyChangeListener Methods
-
- /**
- * Process property change events from our associated Context.
- *
- * @param event The property change event that has occurred
- */
- public void propertyChange(PropertyChangeEvent event) {
-
- // Validate the source of this event
- if (!(event.getSource() instanceof Context))
- return;
- Context context = (Context) event.getSource();
-
- // Process a relevant property change
- if (event.getPropertyName().equals("reloadable")) {
- try {
- setReloadable(((Boolean) event.getNewValue()).booleanValue());
- } catch (NumberFormatException e) {
- log.error(sm.getString("webappLoader.reloadable",
- event.getNewValue().toString()));
- }
- }
-
- }
-
- // ------------------------------------------------------- Private Methods
-
- /**
- * Create associated classLoader. GOOGLE: Added type information.
- */
- private WebappClassLoader createClassLoader() throws Exception {
-
- Class<?> clazz = Class.forName(loaderClass);
- WebappClassLoader classLoader = null;
-
- if (parentClassLoader == null) {
- parentClassLoader = Thread.currentThread().getContextClassLoader();
- }
- Class<?>[] argTypes = {ClassLoader.class};
- Object[] args = {parentClassLoader};
- Constructor<?> constr = clazz.getConstructor(argTypes);
- classLoader = (WebappClassLoader) constr.newInstance(args);
-
- return classLoader;
-
- }
-
- /**
- * Log a message on the Logger associated with our Container (if any)
- *
- * @param message Message to be logged
- */
- private void log(String message) {
-
- Logger logger = null;
- if (container != null)
- logger = container.getLogger();
- if (logger != null)
- logger.log("WebappLoader[" + container.getName() + "]: " + message);
- else {
- String containerName = null;
- if (container != null)
- containerName = container.getName();
- System.out.println("WebappLoader[" + containerName + "]: " + message);
- }
-
- }
-
- /**
- * Log a message on the Logger associated with our Container (if any)
- *
- * @param message Message to be logged
- * @param throwable Associated exception
- */
- private void log(String message, Throwable throwable) {
-
- Logger logger = null;
- if (container != null)
- logger = container.getLogger();
- if (logger != null) {
- logger.log("WebappLoader[" + container.getName() + "] " + message,
- throwable);
- } else {
- String containerName = null;
- if (container != null)
- containerName = container.getName();
- System.out.println("WebappLoader[" + containerName + "]: " + message);
- System.out.println("" + throwable);
- throwable.printStackTrace(System.out);
- }
-
- }
-
- /**
- * Configure associated class loader permissions.
- */
- private void setPermissions() {
-
- if (System.getSecurityManager() == null)
- return;
- if (!(container instanceof Context))
- return;
-
- // Tell the class loader the root of the context
- ServletContext servletContext = ((Context) container).getServletContext();
-
- // Assigning permissions for the work directory
- File workDir = (File) servletContext.getAttribute(Globals.WORK_DIR_ATTR);
- if (workDir != null) {
- try {
- String workDirPath = workDir.getCanonicalPath();
- classLoader.addPermission(new FilePermission(workDirPath, "read,write"));
- classLoader.addPermission(new FilePermission(workDirPath
- + File.separator + "-", "read,write,delete"));
- } catch (IOException e) {
- // Ignore
- }
- }
-
- try {
-
- URL rootURL = servletContext.getResource("/");
- classLoader.addPermission(rootURL);
-
- String contextRoot = servletContext.getRealPath("/");
- if (contextRoot != null) {
- try {
- contextRoot = (new File(contextRoot)).getCanonicalPath();
- classLoader.addPermission(contextRoot);
- } catch (IOException e) {
- // Ignore
- }
- }
-
- URL classesURL = servletContext.getResource("/WEB-INF/classes/");
- classLoader.addPermission(classesURL);
- URL libURL = servletContext.getResource("/WEB-INF/lib/");
- classLoader.addPermission(libURL);
-
- if (contextRoot != null) {
-
- if (libURL != null) {
- File rootDir = new File(contextRoot);
- File libDir = new File(rootDir, "WEB-INF/lib/");
- try {
- String path = libDir.getCanonicalPath();
- classLoader.addPermission(path);
- } catch (IOException e) {
- }
- }
-
- } else {
-
- if (workDir != null) {
- if (libURL != null) {
- File libDir = new File(workDir, "WEB-INF/lib/");
- try {
- String path = libDir.getCanonicalPath();
- classLoader.addPermission(path);
- } catch (IOException e) {
- }
- }
- if (classesURL != null) {
- File classesDir = new File(workDir, "WEB-INF/classes/");
- try {
- String path = classesDir.getCanonicalPath();
- classLoader.addPermission(path);
- } catch (IOException e) {
- }
- }
- }
-
- }
-
- } catch (MalformedURLException e) {
- }
-
- }
-
- /**
- * Configure the repositories for our class loader, based on the associated
- * Context. GOOGLE: Added type information.
- */
- private void setRepositories() {
-
- if (!(container instanceof Context))
- return;
- ServletContext servletContext = ((Context) container).getServletContext();
- if (servletContext == null)
- return;
-
- loaderRepositories = new ArrayList<String>();
- // Loading the work directory
- File workDir = (File) servletContext.getAttribute(Globals.WORK_DIR_ATTR);
- if (workDir == null) {
- log.info("No work dir for " + servletContext);
- }
-
- if (log.isDebugEnabled())
- log.debug(sm.getString("webappLoader.deploy", workDir.getAbsolutePath()));
-
- classLoader.setWorkDir(workDir);
-
- DirContext resources = container.getResources();
-
- // Setting up the class repository (/WEB-INF/classes), if it exists
-
- String classesPath = "/WEB-INF/classes";
- DirContext classes = null;
-
- try {
- Object object = resources.lookup(classesPath);
- if (object instanceof DirContext) {
- classes = (DirContext) object;
- }
- } catch (NamingException e) {
- // Silent catch: it's valid that no /WEB-INF/classes collection
- // exists
- }
-
- if (classes != null) {
-
- File classRepository = null;
-
- String absoluteClassesPath = servletContext.getRealPath(classesPath);
-
- if (absoluteClassesPath != null) {
-
- classRepository = new File(absoluteClassesPath);
-
- } else {
-
- classRepository = new File(workDir, classesPath);
- classRepository.mkdirs();
- copyDir(classes, classRepository);
-
- }
-
- if (log.isDebugEnabled())
- log.debug(sm.getString("webappLoader.classDeploy", classesPath,
- classRepository.getAbsolutePath()));
-
- // Adding the repository to the class loader
- classLoader.addRepository(classesPath + "/", classRepository);
- loaderRepositories.add(classesPath + "/");
-
- }
-
- // Setting up the JAR repository (/WEB-INF/lib), if it exists
-
- String libPath = "/WEB-INF/lib";
-
- classLoader.setJarPath(libPath);
-
- DirContext libDir = null;
- // Looking up directory /WEB-INF/lib in the context
- try {
- Object object = resources.lookup(libPath);
- if (object instanceof DirContext)
- libDir = (DirContext) object;
- } catch (NamingException e) {
- // Silent catch: it's valid that no /WEB-INF/lib collection
- // exists
- }
-
- if (libDir != null) {
-
- boolean copyJars = false;
- String absoluteLibPath = servletContext.getRealPath(libPath);
-
- File destDir = null;
-
- if (absoluteLibPath != null) {
- destDir = new File(absoluteLibPath);
- } else {
- copyJars = true;
- destDir = new File(workDir, libPath);
- destDir.mkdirs();
- }
-
- // Looking up directory /WEB-INF/lib in the context
- try {
- // GOOGLE: "enum" is a reserved word in JDK 1.5
- NamingEnumeration<Binding> enum_ = resources.listBindings(libPath);
- while (enum_.hasMoreElements()) {
-
- Binding binding = enum_.nextElement();
- String filename = libPath + "/" + binding.getName();
- if (!filename.endsWith(".jar"))
- continue;
-
- // Copy JAR in the work directory, always (the JAR file
- // would get locked otherwise, which would make it
- // impossible to update it or remove it at runtime)
- File destFile = new File(destDir, binding.getName());
-
- if (log.isDebugEnabled())
- log.debug(sm.getString("webappLoader.jarDeploy", filename,
- destFile.getAbsolutePath()));
-
- Resource jarResource = (Resource) binding.getObject();
- if (copyJars) {
- if (!copy(jarResource.streamContent(), new FileOutputStream(
- destFile)))
- continue;
- }
-
- try {
- JarFile jarFile = new JarFile(destFile);
- classLoader.addJar(filename, jarFile, destFile);
- } catch (Exception ex) {
- // Catch the exception if there is an empty jar file
- // Should ignore and continute loading other jar files
- // in the dir
- }
-
- loaderRepositories.add(filename);
-
- }
- } catch (NamingException e) {
- // Silent catch: it's valid that no /WEB-INF/lib directory
- // exists
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- }
-
- }
-
- /**
- * Set the appropriate context attribute for our class path. This is required
- * only because Jasper depends on it.
- */
- private void setClassPath() {
-
- // Validate our current state information
- if (!(container instanceof Context))
- return;
- ServletContext servletContext = ((Context) container).getServletContext();
- if (servletContext == null)
- return;
-
- if (container instanceof StandardContext) {
- String baseClasspath = ((StandardContext) container).getCompilerClasspath();
- if (baseClasspath != null) {
- servletContext.setAttribute(Globals.CLASS_PATH_ATTR, baseClasspath);
- return;
- }
- }
-
- StringBuffer classpath = new StringBuffer();
-
- // Assemble the class path information from our class loader chain
- ClassLoader loader = getClassLoader();
- int layers = 0;
- int n = 0;
- while (loader != null) {
- if (!(loader instanceof URLClassLoader)) {
- String cp = getClasspath(loader);
- if (cp == null) {
- log.info("Unknown loader " + loader + " " + loader.getClass());
- break;
- } else {
- if (n > 0)
- classpath.append(File.pathSeparator);
- classpath.append(cp);
- n++;
- }
- break;
- // continue;
- }
- URL repositories[] = ((URLClassLoader) loader).getURLs();
- for (int i = 0; i < repositories.length; i++) {
- String repository = repositories[i].toString();
- if (repository.startsWith("file://"))
- repository = repository.substring(7);
- else if (repository.startsWith("file:"))
- repository = repository.substring(5);
- else if (repository.startsWith("jndi:"))
- repository = servletContext.getRealPath(repository.substring(5));
- else
- continue;
- if (repository == null)
- continue;
- if (n > 0)
- classpath.append(File.pathSeparator);
- classpath.append(repository);
- n++;
- }
- loader = loader.getParent();
- layers++;
- }
-
- this.classpath = classpath.toString();
-
- // Store the assembled class path as a servlet context attribute
- servletContext.setAttribute(Globals.CLASS_PATH_ATTR, classpath.toString());
-
- }
-
- // try to extract the classpath from a loader that is not URLClassLoader
- private String getClasspath(ClassLoader loader) {
- try {
- Method m = loader.getClass().getMethod("getClasspath", new Class[] {});
- if (log.isTraceEnabled())
- log.trace("getClasspath " + m);
- if (m == null)
- return null;
- Object o = m.invoke(loader, new Object[] {});
- if (log.isDebugEnabled())
- log.debug("gotClasspath " + o);
- if (o instanceof String)
- return (String) o;
- return null;
- } catch (Exception ex) {
- if (log.isDebugEnabled())
- log.debug("getClasspath ", ex);
- }
- return null;
- }
-
- /**
- * Copy directory.
- */
- private boolean copyDir(DirContext srcDir, File destDir) {
-
- try {
-
- // GOOGLE: "enum" is a reserved word in JDK 1.5
- NamingEnumeration<NameClassPair> enum_ = srcDir.list("");
- while (enum_.hasMoreElements()) {
- NameClassPair ncPair = enum_.nextElement();
- String name = ncPair.getName();
- Object object = srcDir.lookup(name);
- File currentFile = new File(destDir, name);
- if (object instanceof Resource) {
- InputStream is = ((Resource) object).streamContent();
- OutputStream os = new FileOutputStream(currentFile);
- if (!copy(is, os))
- return false;
- } else if (object instanceof InputStream) {
- OutputStream os = new FileOutputStream(currentFile);
- if (!copy((InputStream) object, os))
- return false;
- } else if (object instanceof DirContext) {
- currentFile.mkdir();
- copyDir((DirContext) object, currentFile);
- }
- }
-
- } catch (NamingException e) {
- return false;
- } catch (IOException e) {
- return false;
- }
-
- return true;
-
- }
-
- /**
- * Copy a file to the specified temp directory. This is required only because
- * Jasper depends on it.
- */
- private boolean copy(InputStream is, OutputStream os) {
-
- try {
- byte[] buf = new byte[4096];
- while (true) {
- int len = is.read(buf);
- if (len < 0)
- break;
- os.write(buf, 0, len);
- }
- is.close();
- os.close();
- } catch (IOException e) {
- return false;
- }
-
- return true;
-
- }
-
- private static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(WebappLoader.class);
-
- private ObjectName oname;
- private MBeanServer mserver;
- private String domain;
- private ObjectName controller;
-
- public ObjectName preRegister(MBeanServer server, ObjectName name)
- throws Exception {
- oname = name;
- mserver = server;
- domain = name.getDomain();
-
- return name;
- }
-
- public void postRegister(Boolean registrationDone) {
- }
-
- public void preDeregister() throws Exception {
- }
-
- public void postDeregister() {
- }
-
- public ObjectName getController() {
- return controller;
- }
-
- public void setController(ObjectName controller) {
- this.controller = controller;
- }
-
-}