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&apos;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

Reply via email to