Author: fhanik
Date: Tue Aug 21 12:00:23 2007
New Revision: 568233
URL: http://svn.apache.org/viewvc?rev=568233&view=rev
Log:
Extend the virtual loader a bit further, allowing developers to specify a
class-path using the MANIFEST.MF file in the WAR file. I can't see that it
would break the spec, and Websphere does it.
Modified:
tomcat/trunk/java/org/apache/catalina/loader/VirtualWebappLoader.java
Modified: tomcat/trunk/java/org/apache/catalina/loader/VirtualWebappLoader.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/loader/VirtualWebappLoader.java?rev=568233&r1=568232&r2=568233&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/loader/VirtualWebappLoader.java
(original)
+++ tomcat/trunk/java/org/apache/catalina/loader/VirtualWebappLoader.java Tue
Aug 21 12:00:23 2007
@@ -17,14 +17,20 @@
package org.apache.catalina.loader;
import java.io.File;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.StringTokenizer;
+import java.util.jar.Attributes;
import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+import javax.naming.NamingException;
+import javax.naming.directory.DirContext;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.ExpandWar;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
+import org.apache.naming.resources.Resource;
/**
* Simple webapp classloader that allows a customized classpath to be added
@@ -41,13 +47,16 @@
* but be kept separate during runtime.
*
* The separator for the virtualClasspath defaulted to ; but can be configured
using the separator attribute
- *
+ *
+ * IF the attribute readManifestCP is set to true, the Class-Path from the WAR
files META-INF/MANIFEST.MF file is also read.
* <code>
* <Context docBase="\webapps\mydocbase">
* <Loader className="org.apache.catalina.loader.VirtualWebappLoader"
* virtualClasspath="\dir\classes:\somedir\somejar.jar"
* makeLocalCopy="true"
- * separator=":"/>
+ * separator=":"
+ * separateJars="true"
+ * readManifestCP="true"/>
* </Context>
* </code>
*
@@ -73,7 +82,7 @@
/**
* Should we make a copy of the libraries upon startup
*/
- protected boolean makeLocalCopy = false;
+ protected boolean makeLocalCopy = true;
/**
* The location of the libraries.
@@ -84,6 +93,17 @@
* The path seperator
*/
protected String separator = ";";
+
+ /**
+ * Separate Jars, means that Jars will be loaded
+ * into the classloaded, in a non locking way.
+ */
+ protected boolean separateJars = true;
+
+ /**
+ * Read the manifest class-path
+ */
+ protected boolean readManifestCP = true;
/**
* Construct a new WebappLoader with no defined parent class loader (so
that
* the actual parent will be the system class loader).
@@ -120,6 +140,14 @@
this.separator = separator;
}
+ public void setReadManifestCP(boolean readManifestCP) {
+ this.readManifestCP = readManifestCP;
+ }
+
+ public void setSeparateJars(boolean separateJars) {
+ this.separateJars = separateJars;
+ }
+
@Override
public void start() throws LifecycleException {
if (log.isInfoEnabled()) log.info("Starting VirtualWebappLoader
for:"+getContainer().getName());
@@ -141,35 +169,16 @@
}
tempDir.mkdirs();
}
- StringTokenizer tkn = new StringTokenizer(virtualClasspath, separator);
- while (tkn!=null && tkn.hasMoreTokens()) {
- String ftkn = tkn.nextToken();
- if (ftkn==null) continue;
- File file = new File(ftkn);
- if (!file.exists()) {
- continue;
- }
- File tmpFile = file;
- if (makeLocalCopy) {
- tmpFile = new File(tempDir, file.getName());
- if (log.isDebugEnabled()) log.debug("Creating local
copy:"+tmpFile.getAbsolutePath());
- if (!ExpandWar.copy(file, tmpFile)) throw new
LifecycleException("Unable to copy resources:"+file.getAbsolutePath());
- }
- if (tmpFile.isDirectory()) {
- if (log.isDebugEnabled()) log.debug("Adding directory to
virtual repo:"+tmpFile.getAbsolutePath());
- addRepository("file:/" + tmpFile.getAbsolutePath() + "/");
- } else if (tmpFile.getAbsolutePath().endsWith(".jar")) {
- //addRepository("file:/" + tmpFile.getAbsolutePath());
- jarFiles.add(tmpFile.getAbsolutePath());
- } else {
- if (log.isDebugEnabled()) log.debug("Adding file to virtual
repo:"+tmpFile.getAbsolutePath());
- addRepository("file:/" + tmpFile.getAbsolutePath());
- }
- }
+ processClassPath(virtualClasspath,jarFiles,separator);
+
+ processManifest(jarFiles);
+
if (log.isDebugEnabled()) log.debug("Starting parent WebappLoader");
super.start();
+ //jars were added as a regular repository above
+ if (!separateJars) return;
//add JarFiles to the classloader, we can't do that before we start
//since there is no classloader during that time
@@ -185,9 +194,67 @@
wloader.addJar(filename,jfile,file);
}catch ( Exception iox) {
if (log.isDebugEnabled()) log.debug("",iox);
+ }//catch
+ }//for
+ }//end if
+ }
+
+ protected void processManifest(ArrayList<String> jarFiles) throws
LifecycleException {
+ //process the meta inf directory
+ DirContext resources = getContainer().getResources();
+ // Setting up the class repository (/WEB-INF/classes), if it exists
+ String metainfPath = "/META-INF";
+ DirContext metainf = null;
+ try {
+ Object object = resources.lookup(metainfPath);
+ if (object instanceof DirContext) {
+ metainf = (DirContext) object;
+ Object o = metainf.lookup("MANIFEST.MF");
+ if (o!=null && o instanceof Resource) {
+ Manifest mf = new Manifest(((Resource)o).streamContent());
+ Attributes attr = mf.getMainAttributes();
+ String classpath = (String)attr.getValue("Class-Path");
+ if ( classpath != null )
processClassPath(classpath,jarFiles," ");
}
}
- }
+ } catch(IOException e) {
+ //unable to read manifest
+ log.debug("Unable to read manifest.",e);
+ } catch(NamingException e) {
+ // Silent catch: it's valid that no /META-INF collection exists
+ }
+ }
+
+ private void processClassPath(String classpath, ArrayList<String>
jarFiles, String sep) throws LifecycleException {
+ StringTokenizer tkn = new StringTokenizer(classpath, sep);
+ while (tkn!=null && tkn.hasMoreTokens()) {
+ String ftkn = tkn.nextToken();
+ if (ftkn==null) continue;
+ File file = new File(ftkn);
+ addRepository(jarFiles, file);
+ }
+ }
+
+ protected void addRepository(ArrayList<String> jarFiles, File file) throws
LifecycleException {
+ if (!file.exists()) {
+ return;
+ }
+ File tmpFile = file;
+ if (makeLocalCopy) {
+ tmpFile = new File(tempDir, file.getName());
+ if (log.isDebugEnabled()) log.debug("Creating local
copy:"+tmpFile.getAbsolutePath());
+ if (!ExpandWar.copy(file, tmpFile)) throw new
LifecycleException("Unable to copy resources:"+file.getAbsolutePath());
+ }
+ if (tmpFile.isDirectory()) {
+ if (log.isDebugEnabled()) log.debug("Adding directory to virtual
repo:"+tmpFile.getAbsolutePath());
+ addRepository("file:/" + tmpFile.getAbsolutePath() + "/");
+ } else if (tmpFile.getAbsolutePath().endsWith(".jar") && separateJars)
{
+ //addRepository("file:/" + tmpFile.getAbsolutePath());
+ jarFiles.add(tmpFile.getAbsolutePath());
+ } else {
+ if (log.isDebugEnabled()) log.debug("Adding file to virtual
repo:"+tmpFile.getAbsolutePath());
+ addRepository("file:/" + tmpFile.getAbsolutePath());
+ }
}
@Override
@@ -204,5 +271,17 @@
public String getSeparator() {
return separator;
+ }
+
+ public boolean getSeparateJars() {
+ return separateJars;
+ }
+
+ public boolean getReadManifestCP() {
+ return readManifestCP;
+ }
+
+ public String getVirtualClasspath() {
+ return virtualClasspath;
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]