Author: markt Date: Thu Jul 20 14:13:48 2017 New Revision: 1802490 URL: http://svn.apache.org/viewvc?rev=1802490&view=rev Log: Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=60963 Add a new WebResourceRoot implementation that extracts JARs to the work directory for improved performance when deploying packed WAR files.
Added: tomcat/trunk/java/org/apache/catalina/webresources/ExtractingRoot.java (with props) Modified: tomcat/trunk/java/org/apache/catalina/core/StandardContext.java tomcat/trunk/java/org/apache/catalina/webresources/LocalStrings.properties tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java tomcat/trunk/webapps/docs/changelog.xml tomcat/trunk/webapps/docs/config/host.xml tomcat/trunk/webapps/docs/config/resources.xml Modified: tomcat/trunk/java/org/apache/catalina/core/StandardContext.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/StandardContext.java?rev=1802490&r1=1802489&r2=1802490&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/core/StandardContext.java (original) +++ tomcat/trunk/java/org/apache/catalina/core/StandardContext.java Thu Jul 20 14:13:48 2017 @@ -4864,6 +4864,9 @@ public class StandardContext extends Con namingResources.start(); } + // Post work directory + postWorkDirectory(); + // Add missing components as necessary if (getResources() == null) { // (1) Required by Loader if (log.isDebugEnabled()) @@ -4894,9 +4897,6 @@ public class StandardContext extends Con // Initialize character set mapper getCharsetMapper(); - // Post work directory - postWorkDirectory(); - // Validate required extensions boolean dependencyCheck = true; try { Added: tomcat/trunk/java/org/apache/catalina/webresources/ExtractingRoot.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/ExtractingRoot.java?rev=1802490&view=auto ============================================================================== --- tomcat/trunk/java/org/apache/catalina/webresources/ExtractingRoot.java (added) +++ tomcat/trunk/java/org/apache/catalina/webresources/ExtractingRoot.java Thu Jul 20 14:13:48 2017 @@ -0,0 +1,106 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.catalina.webresources; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import javax.servlet.ServletContext; + +import org.apache.catalina.LifecycleException; +import org.apache.catalina.WebResource; +import org.apache.catalina.startup.ExpandWar; +import org.apache.catalina.util.IOTools; +import org.apache.tomcat.util.res.StringManager; + +/** + * If the main resources are packaged as a WAR file then any JARs will be + * extracted to the work directory and used from there. + */ +public class ExtractingRoot extends StandardRoot { + + private static final StringManager sm = StringManager.getManager(ExtractingRoot.class); + + private static final String APPLICATION_JARS_DIR = "application-jars"; + + @Override + protected void processWebInfLib() throws LifecycleException { + + // Don't extract JAR files unless the application is deployed as a + // packed WAR file. + if (!super.isPackedWarFile()) { + super.processWebInfLib(); + return; + } + + File expansionTarget = getExpansionTarget(); + if (!expansionTarget.isDirectory()) { + if (!expansionTarget.mkdirs()) { + throw new LifecycleException( + sm.getString("extractingRoot.targetFailed", expansionTarget)); + } + } + + WebResource[] possibleJars = listResources("/WEB-INF/lib", false); + + for (WebResource possibleJar : possibleJars) { + if (possibleJar.isFile() && possibleJar.getName().endsWith(".jar")) { + try { + File dest = new File(expansionTarget, possibleJar.getName()); + dest = dest.getCanonicalFile(); + try (InputStream sourceStream = possibleJar.getInputStream(); + OutputStream destStream= new FileOutputStream(dest)) { + IOTools.flow(sourceStream, destStream); + } + + createWebResourceSet(ResourceSetType.CLASSES_JAR, + "/WEB-INF/classes", dest.toURI().toURL(), "/"); + } catch (IOException ioe) { + throw new LifecycleException( + sm.getString("extractingRoot.jarFailed", possibleJar.getName()), ioe); + } + } + } + } + + private File getExpansionTarget() { + File tmpDir = (File) getContext().getServletContext().getAttribute(ServletContext.TEMPDIR); + File expansionTarget = new File(tmpDir, APPLICATION_JARS_DIR); + return expansionTarget; + } + + + @Override + protected boolean isPackedWarFile() { + return false; + } + + + @Override + protected void stopInternal() throws LifecycleException { + super.stopInternal(); + + if (super.isPackedWarFile()) { + // Remove the extracted JARs from the work directory + File expansionTarget = getExpansionTarget(); + ExpandWar.delete(expansionTarget); + } + } +} Propchange: tomcat/trunk/java/org/apache/catalina/webresources/ExtractingRoot.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: tomcat/trunk/java/org/apache/catalina/webresources/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/LocalStrings.properties?rev=1802490&r1=1802489&r2=1802490&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/webresources/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/catalina/webresources/LocalStrings.properties Thu Jul 20 14:13:48 2017 @@ -32,6 +32,9 @@ dirResourceSet.notDirectory=The director dirResourceSet.writeExists=The target of the write already exists dirResourceSet.writeNpe=The input stream may not be null +extractingRoot.targetFailed=Failed to create the directory [{0}] for extracted JAR files +extractingRoot.jarFailed=Failed to extract the JAR file [{0}] + fileResource.getCanonicalPathFail=Unable to determine the canonical path for the resource [{0}] fileResource.getCreationFail=Unable to determine the creation time for the resource [{0}] fileResource.getUrlFail=Unable to determine a URL for the resource [{0}] Modified: tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java?rev=1802490&r1=1802489&r2=1802490&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java (original) +++ tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java Thu Jul 20 14:13:48 2017 @@ -344,7 +344,7 @@ public class StandardRoot extends Lifecy return listResources(path, true); } - private WebResource[] listResources(String path, boolean validate) { + protected WebResource[] listResources(String path, boolean validate) { if (validate) { path = validate(path); } @@ -574,8 +574,11 @@ public class StandardRoot extends Lifecy * the methods that are explicitly defined to return class loader resources. * This prevents calls to getResource("/WEB-INF/classes") returning from one * or more of the JAR files. + * + * @throws LifecycleException If an error occurs that should stop the web + * application from starting */ - private void processWebInfLib() { + protected void processWebInfLib() throws LifecycleException { WebResource[] possibleJars = listResources("/WEB-INF/lib", false); for (WebResource possibleJar : possibleJars) { Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1802490&r1=1802489&r2=1802490&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Thu Jul 20 14:13:48 2017 @@ -52,6 +52,12 @@ other class loader resources) when the web application is deployed in a packed WAR file. (markt) </fix> + <fix> + <bug>60963</bug>: Add <code>ExtractingRoot</code>, a new + <code>WebResourceRoot</code> implementation that extracts JARs to the + work directory for improved performance when deploying packed WAR files. + (markt) + </fix> </changelog> </subsection> <subsection name="Web applications"> Modified: tomcat/trunk/webapps/docs/config/host.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/host.xml?rev=1802490&r1=1802489&r2=1802490&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/config/host.xml (original) +++ tomcat/trunk/webapps/docs/config/host.xml Thu Jul 20 14:13:48 2017 @@ -298,7 +298,9 @@ <p>Note: Running with this option set to <code>false</code> will incur a performance penalty. To avoid a significant performance penalty, the web application should be configured such that class scanning for - Servlet 3.0+ pluggability features is not required.</p> + Servlet 3.0+ pluggability features is not required. Users may also wish + to consider the <strong>ExtractingRoot</strong> + <a href="resources.html">Resources</a> implementation.</p> </attribute> <attribute name="workDir" required="false"> Modified: tomcat/trunk/webapps/docs/config/resources.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/resources.xml?rev=1802490&r1=1802489&r2=1802490&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/config/resources.xml (original) +++ tomcat/trunk/webapps/docs/config/resources.xml Thu Jul 20 14:13:48 2017 @@ -149,10 +149,28 @@ <subsection name="Standard Implementation"> + <h3>Standard Root Implementation</h3> + <p>The standard implementation of <strong>Resources</strong> is <strong>org.apache.catalina.webresources.StandardRoot</strong>. It does not support any additional attributes.</p> + <h3>Extracting Root Implementation</h3> + + <p>The extracting implementation of <strong>Resources</strong> is + <strong>org.apache.catalina.webresources.ExtractingRoot</strong>. It does not + support any additional attributes.</p> + + <p>When deploying web applications as packed WAR files, the extracting root + will extract any JAR files from <code>/WEB-INF/lib</code> to a + <code>application-jars</code> directory located in the web + application's working directory. These extracted JARs will be removed + when the web application stops.</p> + + <p>Extracting JAR files from a packed WAR may provide a performance + improvement, particularly at web application start when JAR scanning is + required by the application.</p> + </subsection> </section> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org