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>
  * &lt;Context docBase="\webapps\mydocbase">
  *   &lt;Loader className="org.apache.catalina.loader.VirtualWebappLoader"
  *              virtualClasspath="\dir\classes:\somedir\somejar.jar"
  *              makeLocalCopy="true"
- *              separator=":"/>
+ *              separator=":"
+ *              separateJars="true"
+ *              readManifestCP="true"/>
  * &lt;/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]

Reply via email to