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]