You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by cr...@locus.apache.org on 2000/05/09 04:35:52 UTC
cvs commit: jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader FileClassLoader.java Reloader.java LocalStrings.properties StandardLoader.java
craigmcc 00/05/08 19:35:50
Modified: proposals/catalina/src/conf server.xml
proposals/catalina/src/share/org/apache/tomcat/loader
LocalStrings.properties StandardLoader.java
Added: proposals/catalina/src/share/org/apache/tomcat/loader
FileClassLoader.java Reloader.java
Log:
Begin factoring of the Loader implementation so that the actual ClassLoader
used can be pluggable, with optional support for auto-reloading. This code
is not yet complete and not yet in use.
Revision Changes Path
1.20 +2 -0 jakarta-tomcat/proposals/catalina/src/conf/server.xml
Index: server.xml
===================================================================
RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/conf/server.xml,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -r1.19 -r1.20
--- server.xml 2000/05/06 00:20:33 1.19
+++ server.xml 2000/05/09 02:35:42 1.20
@@ -51,6 +51,8 @@
<Context path="/examples" docBase="webapps/examples" debug="0">
<Listener className="org.apache.tomcat.startup.ContextConfig"
debug="0"/>
+ <Loader className="org.apache.tomcat.loader.StandardLoader"
+ debug="3"/>
<Manager className="org.apache.tomcat.session.StandardManager"
checkInterval="15" maxActiveSessions="200"
pathname="sessions/localhost_examples.sessions"/>
1.2 +10 -0 jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader/LocalStrings.properties
Index: LocalStrings.properties
===================================================================
RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader/LocalStrings.properties,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- LocalStrings.properties 2000/04/26 02:14:53 1.1
+++ LocalStrings.properties 2000/05/09 02:35:47 1.2
@@ -1,5 +1,15 @@
+fileClassLoader.canRead=Repository {0} cannot be read
+fileClassLoader.exists=Repository {0} does not exist
+fileClassLoader.jarFile=Cannot read JAR file {0}
+standardLoader.addRepository=Adding repository {0}
standardLoader.alreadyStarted=Loader has already been started
standardLoader.exists=Repository {0} does not exist
+standardLoader.includes= Include path {0}
standardLoader.notStarted=Loader has not yet been started
standardLoader.read=Repository {0} cannot be read
+standardLoader.reload=Reloading this Loader
+standardLoader.reloadError=Error reloading this loader
+standardLoader.removeRepository=Removing repository {0}
+standardLoader.starting=Starting this Loader
+standardLoader.stopping=Stopping this Loader
standardLoader.type=Repository {0} is not a supported file type
1.3 +82 -6 jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader/StandardLoader.java
Index: StandardLoader.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader/StandardLoader.java,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- StandardLoader.java 2000/04/29 05:59:55 1.2
+++ StandardLoader.java 2000/05/09 02:35:47 1.3
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader/StandardLoader.java,v 1.2 2000/04/29 05:59:55 craigmcc Exp $
- * $Revision: 1.2 $
- * $Date: 2000/04/29 05:59:55 $
+ * $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader/StandardLoader.java,v 1.3 2000/05/09 02:35:47 craigmcc Exp $
+ * $Revision: 1.3 $
+ * $Date: 2000/05/09 02:35:47 $
*
* ====================================================================
*
@@ -79,6 +79,7 @@
import org.apache.tomcat.LifecycleException;
import org.apache.tomcat.LifecycleListener;
import org.apache.tomcat.Loader;
+import org.apache.tomcat.Logger;
import org.apache.tomcat.loader.AdaptiveClassLoader;
import org.apache.tomcat.util.LifecycleSupport;
import org.apache.tomcat.util.StringManager;
@@ -97,7 +98,7 @@
* is not present, the system class loader will be used instead.
*
* @author Craig R. McClanahan
- * @version $Revision: 1.2 $ $Date: 2000/04/29 05:59:55 $
+ * @version $Revision: 1.3 $ $Date: 2000/05/09 02:35:47 $
*/
public final class StandardLoader
@@ -219,7 +220,10 @@
*/
public void setDebug(int debug) {
+ int oldDebug = this.debug;
this.debug = debug;
+ support.firePropertyChange("debug", new Integer(oldDebug),
+ new Integer(this.debug));
}
@@ -258,8 +262,13 @@
*/
public void addRepository(String repository) {
- if (!repositories.contains(repository))
+ if (debug >= 1)
+ log(sm.getString("standardLoader.addRepository", repository));
+ if (!repositories.contains(repository)) {
repositories.addElement(repository);
+ if (started)
+ reload();
+ }
}
@@ -303,10 +312,14 @@
*/
public void reload() {
+ if (debug >= 1)
+ log(sm.getString("standardLoader.reload"));
+
try {
stop();
start();
} catch (Throwable t) {
+ log(sm.getString("standardLoader.reloadError"), t);
throw new IllegalStateException("reload: " + t);
}
@@ -332,7 +345,13 @@
*/
public void removeRepository(String repository) {
- repositories.removeElement(repository);
+ if (debug >= 1)
+ log(sm.getString("standardLoader.removeRepository", repository));
+ if (repositories.contains(repository)) {
+ repositories.removeElement(repository);
+ if (started)
+ reload();
+ }
}
@@ -375,6 +394,8 @@
if (started)
throw new LifecycleException
(sm.getString("standardLoader.alreadyStarted"));
+ if (debug >= 1)
+ log(sm.getString("standardLoader.starting"));
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;
@@ -399,6 +420,8 @@
else if (!checkType(file))
throw new LifecycleException
(sm.getString("standardLoader.type", path));
+ if (debug >= 1)
+ log(sm.getString("standardLoader.includes", path));
}
// Construct a new class loader instance for our use
@@ -422,6 +445,8 @@
if (!started)
throw new LifecycleException
(sm.getString("standardLoader.notStarted"));
+ if (debug >= 1)
+ log(sm.getString("standardLoader.stopping"));
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
started = false;
@@ -463,6 +488,57 @@
}
}
return (isArchive);
+
+ }
+
+
+ /**
+ * 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("StandardLoader[" + container.getName() + "]: "
+ + message);
+ else {
+ String containerName = null;
+ if (container != null)
+ containerName = container.getName();
+ System.out.println("StandardLoader[" + 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("StandardLoader[" + container.getName() + "] "
+ + message, throwable);
+ else {
+ String containerName = null;
+ if (container != null)
+ containerName = container.getName();
+ System.out.println("StandardLoader[" + containerName
+ + "]: " + message);
+ System.out.println("" + throwable);
+ throwable.printStackTrace(System.out);
+ }
}
1.1 jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader/FileClassLoader.java
Index: FileClassLoader.java
===================================================================
/*
* $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader/FileClassLoader.java,v 1.1 2000/05/09 02:35:46 craigmcc Exp $
* $Revision: 1.1 $
* $Date: 2000/05/09 02:35:46 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* [Additional notices, if required by prior licensing conditions]
*
*/
package org.apache.tomcat.loader;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import java.util.jar.JarEntry;
import java.util.jar.JarException;
import java.util.jar.JarFile;
import org.apache.tomcat.util.StringManager;
/**
* Implementation of <b>java.lang.ClassLoader</b> that knows how to load
* classes from disk directories and JAR files. It also implements
* the <code>Reloader</code> interface, to provide automatic reloading
* support to <code>StandardLoader</code>.
* <p>
* This code was partially based on the <code>AdaptiveClassLoader</code>
* module originally copied from Apache JServ, and used in Tomcat 3.x.
*
* @author Craig R. McClanahan
* @version $Revision: 1.1 $ $Date: 2000/05/09 02:35:46 $
*/
public final class FileClassLoader
extends ClassLoader
implements Reloader{
// ---------------------------------------------------------- Constructors
/**
* Construct a new ClassLoader instance with no defined repositories.
*/
public FileClassLoader() {
super();
}
/**
* Construct a new ClassLoader instance with the specified initial list of
* repositories. Each element of this list must be a String that contains
* a pathname to a directory, a JAR file, or a ZIP file.
*
* @param repositories Initial list of repositories
*
* @exception IllegalArgumentException if one of the specified repositories
* does not exist, or is not of the appropriate type
*/
public FileClassLoader(Enumeration repositories) {
super();
while (repositories.hasMoreElements())
addRepository((String) repositories.nextElement());
}
// ---------------------------------------------------- Instance Variables
/**
* The set of CacheEntries for classes loaded by this class loader,
* keyed by the fully qualified class name.
*/
private Hashtable cache = new Hashtable();
/**
* The debugging detail level of this component.
*/
private int debug = 0;
/**
* The set of File entries for repositories that are directories,
* keyed by repository name.
*/
private Hashtable directories = new Hashtable();
/**
* The set of File entries for repositories that are JARs,
* keyed by repository name.
*/
private Hashtable jarFiles = new Hashtable();
/**
* The set of repositories associated with this class loader. The order
* of the elements in this Vector controls the order in which repositories
* are examined when new classes or resources are requested.
*/
private Vector repositories = new Vector();
/**
* The string manager for this package.
*/
private static final StringManager sm =
StringManager.getManager(Constants.Package);
// ------------------------------------------------------------ Properties
/**
* Return the debugging detail level of this component.
*/
public int getDebug() {
return (this.debug);
}
/**
* Set the debugging detail level of this component.
*
* @param debug The new debugging detail level
*/
public void setDebug(int debug) {
this.debug = debug;
}
// ------------------------------------------------------- Reloader Methods
/**
* Add a new repository to the set of places this ClassLoader can look for
* classes to be loaded.
*
* @param repository Name of a source of classes to be loaded, such as a
* directory pathname, a JAR file pathname, or a ZIP file pathname
*
* @exception IllegalArgumentException if the specified repository is
* invalid or does not exist
*/
public void addRepository(String repository) {
if (repositories.contains(repository))
return;
// Validate the existence, readability, and type of this repository
File file = new File(repository);
if (!file.exists())
throw new IllegalArgumentException
(sm.getString("fileClassLoader.exists", repository));
if (!file.canRead())
throw new IllegalArgumentException
(sm.getString("fileClassLoader.canRead", repository));
if (file.isDirectory()) {
directories.put(repository, file);
} else {
JarFile jarFile = null;
try {
jarFile = new JarFile(file);
Enumeration entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = (JarEntry) entries.nextElement();
InputStream is = jarFile.getInputStream(entry);
is.close();
break;
}
jarFile.close();
} catch (Throwable t) {
throw new IllegalArgumentException
(sm.getString("fileClassLoader.jarFile", repository));
}
jarFiles.put(repository, file);
}
// Add this repository to the set we know about
repositories.addElement(repository);
}
/**
* Return an enumeration of the current repositories for this class
* loader. If there are no repositories, an empty Enumeration is
* returned.
*/
public Enumeration findRepositories() {
return (repositories.elements());
}
/**
* Have one or more classes or resources been modified so that a reload
* is appropriate?
*/
public boolean modified() {
return (false); // FIXME - modified()
}
/**
* Create a new ClassLoader instance based on our current repositories.
*/
public Reloader reload() {
return (null); // FIXME - reload()
}
/**
* Remove the specified repository from the set of places this ClassLoader
* can look for classes to be loaded. Any classes already loaded from this
* repository will remain, but no future loads from here will take place.
*
* @param repository Name of the repository to remove
*/
public void removeRepository(String repository) {
if (repositories.contains(repository))
repositories.removeElement(repository);
}
// --------------------------------------------------- ClassLoader Methods
/**
* Find a resource with a given name. The return is a URL to the resource.
* Doing a <code>getContent()</code> on the URL may return an Image, an
* AudioClip, or an InputStream.
*
* @param name The name of the resource, to be used as is
*/
public URL getResource(String name) {
// Search for this resource in all of our repositories
Enumeration repositories = this.repositories.elements();
while (repositories.hasMoreElements()) {
String repository = (String) repositories.nextElement();
File directory = (File) directories.get(repository);
if (directory != null) {
URL theURL =
loadResourceFromDirectory(directory, name);
if (theURL != null)
return (theURL);
}
File jarFile = (File) jarFiles.get(repository);
if (jarFile != null) {
URL theURL =
loadResourceFromJarFile(jarFile, name);
if (theURL != null)
return (theURL);
}
}
// Load this resource from the system class path
return (getSystemResource(name));
}
/**
* Get an InputStream on a given resource. Will return <code>null</code>
* if no resource with this name is found.
*
* @param name The name of the resource
*/
public InputStream getResourceAsStream(String name) {
// Search for this resource in all of our repositories
Enumeration repositories = this.repositories.elements();
while (repositories.hasMoreElements()) {
String repository = (String) repositories.nextElement();
File directory = (File) directories.get(repository);
if (directory != null) {
InputStream theStream =
loadStreamFromDirectory(directory, name);
if (theStream != null)
return (theStream);
}
File jarFile = (File) jarFiles.get(repository);
if (jarFile != null) {
InputStream theStream =
loadStreamFromJarFile(jarFile, name);
if (theStream != null)
return (theStream);
}
}
// Load this resource from the system class path
return (getSystemResourceAsStream(name));
}
/**
* Requests the class loader to load and resolve a class with the
* specified name. The <code>loadClass</code> method is called by the
* Java Virtual Machine when a class loaded by a class loader first
* references another class. Every subclass of <code>ClassLoader</code>
* must define this method.
*
* @param name Name of the desired Class
* @param resolve <code>true</code> if this Class needs to be resolved.
*
* @return The resulting Class, or <code>null</code> if it was not found
*
* @exception ClassNotFoundException if the class loader cannot find
* a definition for this class
*/
public Class loadClass(String name, boolean resolve)
throws ClassNotFoundException {
// Has this class already been loaded?
CacheEntry entry = (CacheEntry) cache.get(name);
if (entry != null) {
Class theClass = entry.loadedClass;
if (resolve)
resolveClass(theClass);
return (theClass);
}
// Search for this class in all of our repositories
if (allowed(name)) {
Enumeration repositories = this.repositories.elements();
while (repositories.hasMoreElements()) {
String repository = (String) repositories.nextElement();
File directory = (File) directories.get(repository);
if (directory != null) {
Class theClass =
loadClassFromDirectory(directory, name, resolve);
if (theClass != null)
return (theClass);
}
File jarFile = (File) jarFiles.get(repository);
if (jarFile != null) {
Class theClass =
loadClassFromJarFile(jarFile, name, resolve);
if (theClass != null)
return (theClass);
}
}
}
// Load this class from the system class path
Class theClass = loadClassFromSystem(name, resolve);
if (theClass != null)
return (theClass);
else
throw new ClassNotFoundException(name);
}
// ------------------------------------------------------- Private Methods
/**
* Should we allow this class to be loaded from someplace other than
* the system class path?
*
* @param name Name of the class we are considering
*/
private boolean allowed(String name) {
if (name.startsWith("java."))
return (false);
else
return (true);
}
/**
* Load the specified class from the specified directory, if it exists;
* otherwise return <code>null</code>. If found, a cache entry will be
* automatically added before returning.
*
* @param directory File for the directory to be searched
* @param name Name of the desired class
* @param resolve <code>true</code> if this Class needs to be resolved
*/
private Class loadClassFromDirectory(File directory, String name,
boolean resolve) {
// Translate the class name to a filename
String filename =
name.replace('.', File.separatorChar) + ".class";
// Validate the existence and readability of this class file
File classFile = new File(directory, filename);
if (!classFile.exists() || !classFile.canRead())
return (null);
// Load the bytes for this class, and define it
Class theClass = null;
byte buffer[] = new byte[(int) classFile.length()];
InputStream is = null;
try {
is = new BufferedInputStream(new FileInputStream(classFile));
is.read(buffer);
is.close();
is = null;
theClass = defineClass(name, buffer, 0, buffer.length);
if (resolve)
resolveClass(theClass);
cache.put(name,
new CacheEntry(theClass, classFile,
classFile.lastModified()));
return (theClass);
} catch (Throwable t) {
if (is != null) {
try {
is.close();
} catch (Throwable u) {
;
}
}
return (null);
}
}
/**
* Load the specified class from the specified JAR file, if it exists;
* otherwise return <code>null</code>. If found, a cache entry will be
* automatically added before returning.
*
* @param jar JAR file to be searched
* @param name Name of the desired class
* @param resolve <code>true</code> if this Class needs to be resolved
*/
private Class loadClassFromJarFile(File jar, String name,
boolean resolve) {
// Translate the class name to a filename
String filename =
name.replace('.', '/') + ".class";
// Load the bytes for this class, and define it
JarFile jarFile = null;
JarEntry jarEntry = null;
Class theClass = null;
byte buffer[] = new byte[(int) jarEntry.getSize()];
InputStream is = null;
try {
jarFile = new JarFile(jar);
jarEntry = jarFile.getJarEntry(filename);
if (jarEntry == null) {
jarFile.close();
return (null);
}
is = new BufferedInputStream(jarFile.getInputStream(jarEntry));
is.read(buffer);
is.close();
theClass = defineClass(name, buffer, 0, buffer.length);
if (resolve)
resolveClass(theClass);
cache.put(name,
new CacheEntry(theClass, jar, jar.lastModified()));
return (theClass);
} catch (Throwable t) {
if (is != null) {
try {
is.close();
} catch (Throwable u) {
;
}
}
if (jarFile != null) {
try {
jarFile.close();
} catch (Throwable u) {
;
}
}
return (null);
}
}
/**
* Load the specified class from the system class path, if it exists;
* otherwise return <code>null</code>. If found, a cache entry will be
* automatically added before returning.
*
* @param name Name of the desired class
* @param resolve <code>true</code> if this Class needs to be resolved
*/
private Class loadClassFromSystem(String name, boolean resolve) {
Class theClass = null;
try {
theClass = findSystemClass(name);
} catch (ClassNotFoundException e) {
return (null);
}
if (theClass != null) {
if (resolve)
resolveClass(theClass);
cache.put(name,
new CacheEntry(theClass, null, Long.MAX_VALUE));
return (theClass);
} else
return (null);
}
/**
* Load the specified resource from the specified directory, if it exists;
* otherwise return <code>null</code>.
*
* @param directory File for the directory to be searched
* @param name Name of the desired resource
*/
private URL loadResourceFromDirectory(File directory, String name) {
// Translate the resource name to a filename
String filename =
name.replace('.', File.separatorChar) + ".class";
// Validate the existence and readability of this resource file
File resourceFile = new File(directory, filename);
if (!resourceFile.exists() || !resourceFile.canRead())
return (null);
// Return a URL that points to this resource file
try {
return (new URL("file:" + resourceFile.getAbsolutePath()));
} catch (MalformedURLException e) {
return (null);
}
}
/**
* Load the specified resource from the specified JAR file, if it exists;
* otherwise return <code>null</code>.
*
* @param jar JAR file to be searched
* @param name Name of the desired resource
*/
private URL loadResourceFromJarFile(File jar, String name) {
return (null); // FIXME - loadResourceFromJarFile()
}
/**
* Load the specified resource from the specified directory, if it exists;
* otherwise return <code>null</code>.
*
* @param directory File for the directory to be searched
* @param name Name of the desired resource
*/
private InputStream loadStreamFromDirectory(File directory, String name) {
// Translate the resource name to a filename
String filename = name.replace('.', File.separatorChar);
// Validate the existence and readability of this resource file
File resourceFile = new File(directory, filename);
if (!resourceFile.exists() || !resourceFile.canRead())
return (null);
// Return an input stream for this resource file
try {
return (new FileInputStream(resourceFile));
} catch (IOException e) {
return (null);
}
}
/**
* Load the specified resource from the specified JAR file, if it exists;
* otherwise return <code>null</code>.
*
* @param directory File for the directory to be searched
* @param name Name of the desired resource
*/
private InputStream loadStreamFromJarFile(File jar, String name) {
// Translate the resource name to a filename
String filename = name.replace('.', '/');
// Create an input stream for this resource
JarFile jarFile = null;
JarEntry jarEntry = null;
InputStream is = null;
try {
jarFile = new JarFile(jar);
jarEntry = jarFile.getJarEntry(filename);
if (jarEntry == null) {
jarFile.close();
return (null);
}
is = new BufferedInputStream(jarFile.getInputStream(jarEntry));
jarFile.close();
return (is);
} catch (Throwable t) {
if (jarFile != null) {
try {
jarFile.close();
} catch (Throwable u) {
;
}
}
return (null);
}
}
// ------------------------------------------------------- Private Classes
/**
* The cache entry for a particular class loaded by this class loader.
*/
private static class CacheEntry {
/**
* The "last modified" time of the origin file at the time this class
* was loaded, in milliseconds since the epoch.
*/
long lastModified;
/**
* The actual loaded class.
*/
Class loadedClass;
/**
* The File (for a directory) or JarFile (for a JAR) from which this
* class was loaded, or <code>null</code> if loaded from the system.
*/
Object origin;
/**
* Construct a new instance of this class.
*/
public CacheEntry(Class loadedClass, Object origin,
long lastModified) {
this.loadedClass = loadedClass;
this.origin = origin;
this.lastModified = lastModified;
}
}
}
1.1 jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader/Reloader.java
Index: Reloader.java
===================================================================
/*
* $Header: /home/cvs/jakarta-tomcat/proposals/catalina/src/share/org/apache/tomcat/loader/Reloader.java,v 1.1 2000/05/09 02:35:47 craigmcc Exp $
* $Revision: 1.1 $
* $Date: 2000/05/09 02:35:47 $
*
* ====================================================================
*
* The Apache Software License, Version 1.1
*
* Copyright (c) 1999 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* [Additional notices, if required by prior licensing conditions]
*
*/
package org.apache.tomcat.loader;
import java.util.Enumeration;
/**
* Internal interface that <code>ClassLoader</code> implementations may
* optionally implement to support the auto-reload functionality of
* <code>StandardLoader</code>.
*
* @author Craig R. McClanahan
* @version $Revision: 1.1 $ $Date: 2000/05/09 02:35:47 $
*/
public interface Reloader {
/**
* Add a new repository to the set of places this ClassLoader can look for
* classes to be loaded.
*
* @param repository Name of a source of classes to be loaded, such as a
* directory pathname, a JAR file pathname, or a ZIP file pathname
*
* @exception IllegalArgumentException if the specified repository is
* invalid or does not exist
*/
public void addRepository(String repository);
/**
* Return an enumeration of the current repositories for this class
* loader. If there are no repositories, an empty Enumeration is
* returned.
*/
public Enumeration findRepositories();
/**
* Have one or more classes or resources been modified so that a reload
* is appropriate?
*/
public boolean modified();
/**
* Create a new ClassLoader instance based on our current repositories.
*/
public Reloader reload();
/**
* Remove the specified repository from the set of places this ClassLoader
* can look for classes to be loaded. Any classes already loaded from this
* repository will remain, but no future loads from here will take place.
*
* @param repository Name of the repository to remove
*/
public void removeRepository(String repository);
}