Author: markt
Date: Fri Sep 23 13:05:38 2005
New Revision: 291200

URL: http://svn.apache.org/viewcvs?rev=291200&view=rev
Log:
Fix bug 10026. Port of antiJARLocking functionality from TC5.

Modified:
    
tomcat/container/branches/tc4.1.x/catalina/src/share/org/apache/catalina/core/StandardContext.java
    
tomcat/container/branches/tc4.1.x/catalina/src/share/org/apache/catalina/loader/WebappClassLoader.java
    
tomcat/container/branches/tc4.1.x/catalina/src/share/org/apache/catalina/loader/WebappLoader.java
    
tomcat/container/branches/tc4.1.x/catalina/src/share/org/apache/catalina/mbeans/mbeans-descriptors.xml
    
tomcat/container/branches/tc4.1.x/webapps/admin/WEB-INF/classes/org/apache/webapp/admin/ApplicationResources_en.properties
    
tomcat/container/branches/tc4.1.x/webapps/admin/WEB-INF/classes/org/apache/webapp/admin/context/ContextForm.java
    
tomcat/container/branches/tc4.1.x/webapps/admin/WEB-INF/classes/org/apache/webapp/admin/context/EditContextAction.java
    
tomcat/container/branches/tc4.1.x/webapps/admin/WEB-INF/classes/org/apache/webapp/admin/context/SaveContextAction.java
    tomcat/container/branches/tc4.1.x/webapps/admin/context/context.jsp
    tomcat/container/branches/tc4.1.x/webapps/tomcat-docs/config/context.xml

Modified: 
tomcat/container/branches/tc4.1.x/catalina/src/share/org/apache/catalina/core/StandardContext.java
URL: 
http://svn.apache.org/viewcvs/tomcat/container/branches/tc4.1.x/catalina/src/share/org/apache/catalina/core/StandardContext.java?rev=291200&r1=291199&r2=291200&view=diff
==============================================================================
--- 
tomcat/container/branches/tc4.1.x/catalina/src/share/org/apache/catalina/core/StandardContext.java
 (original)
+++ 
tomcat/container/branches/tc4.1.x/catalina/src/share/org/apache/catalina/core/StandardContext.java
 Fri Sep 23 13:05:38 2005
@@ -111,6 +111,12 @@
 
 
     /**
+     * The antiJARLocking flag for this Context.
+     */
+    private boolean antiJARLocking = false;
+
+    
+    /**
      * The set of application listener class names configured for this
      * application, in the order they were encountered in the web.xml file.
      */
@@ -545,6 +551,32 @@
     }
 
 
+    /**
+     * Return the antiJARLocking flag for this Context.
+     */
+    public boolean getAntiJARLocking() {
+
+        return (this.antiJARLocking);
+
+    }
+
+
+    /**
+     * Set the antiJARLocking feature for this Context.
+     *
+     * @param antiJARLocking The new flag value
+     */
+    public void setAntiJARLocking(boolean antiJARLocking) {
+
+        boolean oldAntiJARLocking = this.antiJARLocking;
+        this.antiJARLocking = antiJARLocking;
+        support.firePropertyChange("antiJARLocking",
+                                   new Boolean(oldAntiJARLocking),
+                                   new Boolean(this.antiJARLocking));
+
+    }
+    
+    
     /**
      * Return the set of initialized application listener objects,
      * in the order they were specified in the web application deployment

Modified: 
tomcat/container/branches/tc4.1.x/catalina/src/share/org/apache/catalina/loader/WebappClassLoader.java
URL: 
http://svn.apache.org/viewcvs/tomcat/container/branches/tc4.1.x/catalina/src/share/org/apache/catalina/loader/WebappClassLoader.java?rev=291200&r1=291199&r2=291200&view=diff
==============================================================================
--- 
tomcat/container/branches/tc4.1.x/catalina/src/share/org/apache/catalina/loader/WebappClassLoader.java
 (original)
+++ 
tomcat/container/branches/tc4.1.x/catalina/src/share/org/apache/catalina/loader/WebappClassLoader.java
 Fri Sep 23 13:05:38 2005
@@ -18,6 +18,7 @@
 package org.apache.catalina.loader;
 
 import java.io.File;
+import java.io.FileOutputStream;
 import java.io.FilePermission;
 import java.io.InputStream;
 import java.io.ByteArrayInputStream;
@@ -312,6 +313,12 @@
 
 
     /**
+     * Path where resources loaded from JARs will be extracted.
+     */
+    protected File loaderDir = null;
+
+
+    /**
      * The PermissionCollection for each CodeSource for a web
      * application context.
      */
@@ -354,6 +361,13 @@
     private Permission allPermission = new java.security.AllPermission();
 
 
+    /**
+     * Use anti JAR locking code, which does URL rerouting when accessing
+     * resources.
+     */
+    boolean antiJARLocking = false; 
+    
+
     // ------------------------------------------------------------- Properties
 
 
@@ -422,6 +436,22 @@
 
 
     /**
+     * @return Returns the antiJARLocking.
+     */
+    public boolean getAntiJARLocking() {
+        return antiJARLocking;
+    }
+    
+    
+    /**
+     * @param antiJARLocking The antiJARLocking to set.
+     */
+    public void setAntiJARLocking(boolean antiJARLocking) {
+        this.antiJARLocking = antiJARLocking;
+    }
+
+    
+    /**
      * If there is a Java SecurityManager create a read FilePermission
      * or JndiPermission for the file directory path.
      *
@@ -498,6 +528,14 @@
     }
 
 
+    /**
+     * Change the work directory.
+     */
+    public void setWorkDir(File workDir) {
+        this.loaderDir = new File(workDir, "loader");
+    }
+
+
     // ------------------------------------------------------- Reloader Methods
 
 
@@ -1130,6 +1168,22 @@
             log("  Searching local repositories");
         url = findResource(name);
         if (url != null) {
+            // Locating the repository for special handling in the case 
+            // of a JAR
+            if (antiJARLocking) {
+                ResourceEntry entry = (ResourceEntry) 
resourceEntries.get(name);
+                try {
+                    String repository = entry.codeBase.toString();
+                    if ((repository.endsWith(".jar")) 
+                            && (!(name.endsWith(".class")))) {
+                        // Copy binary content to the work directory if not 
present
+                        File resourceFile = new File(loaderDir, name);
+                        url = resourceFile.toURL();
+                    }
+                } catch (Exception e) {
+                    // Ignore
+                }
+            }
             if (debug >= 2)
                 log("  --> Returning '" + url.toString() + "'");
             return (url);
@@ -1559,6 +1613,10 @@
         permissionList.clear();
         loaderPC.clear();
 
+        if (loaderDir != null) {
+            deleteDir(loaderDir);
+        }
+
     }
 
 
@@ -1781,6 +1839,57 @@
                 } catch (IOException e) {
                     return null;
                 }
+
+                // Extract resources contained in JAR to the workdir
+                if (antiJARLocking && !(path.endsWith(".class"))) {
+                    byte[] buf = new byte[1024];
+                    File resourceFile = new File
+                        (loaderDir, jarEntry.getName());
+                    if (!resourceFile.exists()) {
+                        Enumeration entries = jarFiles[i].entries();
+                        while (entries.hasMoreElements()) {
+                            JarEntry jarEntry2 = 
+                                (JarEntry) entries.nextElement();
+                            if (!(jarEntry2.isDirectory()) 
+                                && (!jarEntry2.getName().endsWith
+                                    (".class"))) {
+                                resourceFile = new File
+                                    (loaderDir, jarEntry2.getName());
+                                resourceFile.getParentFile().mkdirs();
+                                FileOutputStream os = null;
+                                InputStream is = null;
+                                try {
+                                    is = jarFiles[i].getInputStream
+                                        (jarEntry2);
+                                    os = new FileOutputStream
+                                        (resourceFile);
+                                    while (true) {
+                                        int n = is.read(buf);
+                                        if (n <= 0) {
+                                            break;
+                                        }
+                                        os.write(buf, 0, n);
+                                    }
+                                } catch (IOException e) {
+                                    // Ignore
+                                } finally {
+                                    try {
+                                        if (is != null) {
+                                            is.close();
+                                        }
+                                    } catch (IOException e) {
+                                    }
+                                    try {
+                                        if (os != null) {
+                                            os.close();
+                                        }
+                                    } catch (IOException e) {
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
             }
 
         }
@@ -2074,6 +2183,29 @@
 
     }
 
+    /**
+     * Delete the specified directory, including all of its contents and
+     * subdirectories recursively.
+     *
+     * @param dir File object representing the directory to be deleted
+     */
+    protected static void deleteDir(File dir) {
+
+        String files[] = dir.list();
+        if (files == null) {
+            files = new String[0];
+        }
+        for (int i = 0; i < files.length; i++) {
+            File file = new File(dir, files[i]);
+            if (file.isDirectory()) {
+                deleteDir(file);
+            } else {
+                file.delete();
+            }
+        }
+        dir.delete();
+
+    }
 
 }
 

Modified: 
tomcat/container/branches/tc4.1.x/catalina/src/share/org/apache/catalina/loader/WebappLoader.java
URL: 
http://svn.apache.org/viewcvs/tomcat/container/branches/tc4.1.x/catalina/src/share/org/apache/catalina/loader/WebappLoader.java?rev=291200&r1=291199&r2=291200&view=diff
==============================================================================
--- 
tomcat/container/branches/tc4.1.x/catalina/src/share/org/apache/catalina/loader/WebappLoader.java
 (original)
+++ 
tomcat/container/branches/tc4.1.x/catalina/src/share/org/apache/catalina/loader/WebappLoader.java
 Fri Sep 23 13:05:38 2005
@@ -32,7 +32,6 @@
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.net.URLStreamHandlerFactory;
-import java.security.Permission;
 import java.util.jar.JarFile;
 import javax.servlet.ServletContext;
 import javax.naming.NamingException;
@@ -48,11 +47,11 @@
 import org.apache.catalina.DefaultContext;
 import org.apache.catalina.Globals;
 import org.apache.catalina.Lifecycle;
-import org.apache.catalina.LifecycleEvent;
 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;
 
@@ -609,6 +608,8 @@
             classLoader.setResources(container.getResources());
             classLoader.setDebug(this.debug);
             classLoader.setDelegate(this.delegate);
+            if (container instanceof StandardContext)
+                classLoader.setAntiJARLocking(((StandardContext) 
container).getAntiJARLocking());
 
             for (int i = 0; i < repositories.length; i++) {
                 classLoader.addRepository(repositories[i]);
@@ -913,6 +914,8 @@
             return;
 
         log(sm.getString("webappLoader.deploy", workDir.getAbsolutePath()));
+
+        classLoader.setWorkDir(workDir);
 
         DirContext resources = container.getResources();
 

Modified: 
tomcat/container/branches/tc4.1.x/catalina/src/share/org/apache/catalina/mbeans/mbeans-descriptors.xml
URL: 
http://svn.apache.org/viewcvs/tomcat/container/branches/tc4.1.x/catalina/src/share/org/apache/catalina/mbeans/mbeans-descriptors.xml?rev=291200&r1=291199&r2=291200&view=diff
==============================================================================
--- 
tomcat/container/branches/tc4.1.x/catalina/src/share/org/apache/catalina/mbeans/mbeans-descriptors.xml
 (original)
+++ 
tomcat/container/branches/tc4.1.x/catalina/src/share/org/apache/catalina/mbeans/mbeans-descriptors.xml
 Fri Sep 23 13:05:38 2005
@@ -2077,6 +2077,10 @@
                    is="true"
                  type="boolean"/>
 
+    <attribute name="antiJARLocking"
+               description="Take care to not lock jar files"
+               type="boolean" />
+
     <attribute   name="cacheTTL"
           description="Time interval in ms between cache refeshes"
                  type="int"/>

Modified: 
tomcat/container/branches/tc4.1.x/webapps/admin/WEB-INF/classes/org/apache/webapp/admin/ApplicationResources_en.properties
URL: 
http://svn.apache.org/viewcvs/tomcat/container/branches/tc4.1.x/webapps/admin/WEB-INF/classes/org/apache/webapp/admin/ApplicationResources_en.properties?rev=291200&r1=291199&r2=291200&view=diff
==============================================================================
--- 
tomcat/container/branches/tc4.1.x/webapps/admin/WEB-INF/classes/org/apache/webapp/admin/ApplicationResources_en.properties
 (original)
+++ 
tomcat/container/branches/tc4.1.x/webapps/admin/WEB-INF/classes/org/apache/webapp/admin/ApplicationResources_en.properties
 Fri Sep 23 13:05:38 2005
@@ -157,6 +157,7 @@
 context.checkInterval=Check interval
 context.sessionId=Session ID Initializer
 context.max.sessions=Maximum Active Sessions
+context.antiJarLocking=Prevent Jar Locking
 defaultcontext.properties=DefaultContext Properties
 error.docBase.required=<li>Document base cannot be null</li>
 error.path.required=<li>Path cannot be null</li>

Modified: 
tomcat/container/branches/tc4.1.x/webapps/admin/WEB-INF/classes/org/apache/webapp/admin/context/ContextForm.java
URL: 
http://svn.apache.org/viewcvs/tomcat/container/branches/tc4.1.x/webapps/admin/WEB-INF/classes/org/apache/webapp/admin/context/ContextForm.java?rev=291200&r1=291199&r2=291200&view=diff
==============================================================================
--- 
tomcat/container/branches/tc4.1.x/webapps/admin/WEB-INF/classes/org/apache/webapp/admin/context/ContextForm.java
 (original)
+++ 
tomcat/container/branches/tc4.1.x/webapps/admin/WEB-INF/classes/org/apache/webapp/admin/context/ContextForm.java
 Fri Sep 23 13:05:38 2005
@@ -156,6 +156,11 @@
     private String mgrMaxSessions = "0";
     
     /**
+     * The text for the anti jar locking flag.
+     */
+    private String antiJarLocking = "false";
+
+    /**
      * Set of valid values for debug level.
      */
     private List debugLvlVals = null;
@@ -656,6 +661,20 @@
         
     }
         
+    /**
+     * Get the anti jar locking flag
+     */
+    public String getAntiJarLocking() {
+        return antiJarLocking;
+    }
+
+    /**
+     * Set the anti jar locking flag
+     */
+    public void setAntiJarLocking(String ajl) {
+        antiJarLocking = ajl;
+    }
+
     // --------------------------------------------------------- Public Methods
     
     /**
@@ -680,6 +699,7 @@
         this.path = null;
         this.reloadable = "false";
         this.swallowOutput = "false";        
+        this.antiJarLocking = "false";
         
         // loader properties
         this.ldrCheckInterval = "15";

Modified: 
tomcat/container/branches/tc4.1.x/webapps/admin/WEB-INF/classes/org/apache/webapp/admin/context/EditContextAction.java
URL: 
http://svn.apache.org/viewcvs/tomcat/container/branches/tc4.1.x/webapps/admin/WEB-INF/classes/org/apache/webapp/admin/context/EditContextAction.java?rev=291200&r1=291199&r2=291200&view=diff
==============================================================================
--- 
tomcat/container/branches/tc4.1.x/webapps/admin/WEB-INF/classes/org/apache/webapp/admin/context/EditContextAction.java
 (original)
+++ 
tomcat/container/branches/tc4.1.x/webapps/admin/WEB-INF/classes/org/apache/webapp/admin/context/EditContextAction.java
 Fri Sep 23 13:05:38 2005
@@ -206,6 +206,9 @@
             attribute = "privileged";
             contextFm.setOverride
                 (((Boolean) mBServer.getAttribute(cname, 
attribute)).toString());
+            attribute = "antiJARLocking";
+            contextFm.setAntiJarLocking
+                (((Boolean) mBServer.getAttribute(cname, 
attribute)).toString());
 
             // loader properties
             attribute = "debug";

Modified: 
tomcat/container/branches/tc4.1.x/webapps/admin/WEB-INF/classes/org/apache/webapp/admin/context/SaveContextAction.java
URL: 
http://svn.apache.org/viewcvs/tomcat/container/branches/tc4.1.x/webapps/admin/WEB-INF/classes/org/apache/webapp/admin/context/SaveContextAction.java?rev=291200&r1=291199&r2=291200&view=diff
==============================================================================
--- 
tomcat/container/branches/tc4.1.x/webapps/admin/WEB-INF/classes/org/apache/webapp/admin/context/SaveContextAction.java
 (original)
+++ 
tomcat/container/branches/tc4.1.x/webapps/admin/WEB-INF/classes/org/apache/webapp/admin/context/SaveContextAction.java
 Fri Sep 23 13:05:38 2005
@@ -325,6 +325,16 @@
             mBServer.setAttribute(coname,
                                   new Attribute("useNaming", new 
Boolean(useNaming)));
 
+            attribute = "antiJARLocking";
+            String antiJarLocking = "false";
+            try {
+                antiJarLocking = cform.getAntiJarLocking();
+            } catch (Throwable t) {
+                antiJarLocking = "false";
+            }
+            mBServer.setAttribute(coname,
+                                  new Attribute("antiJARLocking", new 
Boolean(antiJarLocking)));
+
             // Loader properties            
             attribute = "reloadable";
             try {

Modified: tomcat/container/branches/tc4.1.x/webapps/admin/context/context.jsp
URL: 
http://svn.apache.org/viewcvs/tomcat/container/branches/tc4.1.x/webapps/admin/context/context.jsp?rev=291200&r1=291199&r2=291200&view=diff
==============================================================================
--- tomcat/container/branches/tc4.1.x/webapps/admin/context/context.jsp 
(original)
+++ tomcat/container/branches/tc4.1.x/webapps/admin/context/context.jsp Fri Sep 
23 13:05:38 2005
@@ -225,6 +225,17 @@
             </controls:data>
         </controls:row>
 
+      <controls:row labelStyle="table-label-text" 
dataStyle="table-normal-text" styleId="antiJarLocking">
+            <controls:label><bean:message 
key="context.antiJarLocking"/>:</controls:label>
+            <controls:data>
+                <html:select property="antiJarLocking" 
styleId="antiJarLocking">
+                     <bean:define id="booleanVals" name="contextForm" 
property="booleanVals"/>
+                     <html:options collection="booleanVals" property="value"
+                   labelProperty="label"/>
+                </html:select>
+            </controls:data>
+        </controls:row>
+
 <%-- input only allowed on create transaction >
        <controls:row labelStyle="table-label-text" 
dataStyle="table-normal-text" styleId="workdir">
             <controls:label><bean:message 
key="context.workdir"/>:</controls:label>

Modified: 
tomcat/container/branches/tc4.1.x/webapps/tomcat-docs/config/context.xml
URL: 
http://svn.apache.org/viewcvs/tomcat/container/branches/tc4.1.x/webapps/tomcat-docs/config/context.xml?rev=291200&r1=291199&r2=291200&view=diff
==============================================================================
--- tomcat/container/branches/tc4.1.x/webapps/tomcat-docs/config/context.xml 
(original)
+++ tomcat/container/branches/tc4.1.x/webapps/tomcat-docs/config/context.xml 
Fri Sep 23 13:05:38 2005
@@ -185,6 +185,14 @@
 
       </attribute>
 
+      <attribute name="antiJARLocking" required="false">
+        <p>If true, the Tomcat classloader will take extra measures to avoid
+        JAR file locking when resources are accessed inside JARs through URLs.
+        This will impact startup time of applications, but could prove to be 
useful
+        on platforms or configurations where file locking can occur.
+        If not specified, the default value is <code>false</code>.</p>
+      </attribute>
+
       <attribute name="cacheTTL" required="false">
         <p>Amount of time in milliseconds between cache entries revalidation.
         If not specified, the default value is <code>5000</code> 



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to