Author: markt
Date: Tue Nov  5 00:06:50 2013
New Revision: 1538836

URL: http://svn.apache.org/r1538836
Log:
First cut at adding resource tracking

Added:
    tomcat/trunk/java/org/apache/catalina/WebResourceTraceWrapper.java
    
tomcat/trunk/java/org/apache/catalina/webresources/TraceWrapperInputStream.java
Modified:
    tomcat/trunk/java/org/apache/catalina/WebResourceRoot.java
    tomcat/trunk/java/org/apache/catalina/webresources/AbstractResource.java
    tomcat/trunk/java/org/apache/catalina/webresources/FileResource.java
    tomcat/trunk/java/org/apache/catalina/webresources/JarResource.java
    tomcat/trunk/java/org/apache/catalina/webresources/JarResourceRoot.java
    tomcat/trunk/java/org/apache/catalina/webresources/JarWarResource.java
    tomcat/trunk/java/org/apache/catalina/webresources/LocalStrings.properties
    tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java

Modified: tomcat/trunk/java/org/apache/catalina/WebResourceRoot.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/WebResourceRoot.java?rev=1538836&r1=1538835&r2=1538836&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/WebResourceRoot.java (original)
+++ tomcat/trunk/java/org/apache/catalina/WebResourceRoot.java Tue Nov  5 
00:06:50 2013
@@ -360,6 +360,33 @@ public interface WebResourceRoot extends
     long getCacheMaxObjectSize();
 
     /**
+     * Controls whether the trace locked files feature is enabled. If enabled,
+     * all calls to methods that return objects that lock a file and need to be
+     * closed to release that lock (e.g. {@link WebResource#getInputStream()}
+     * will perform a number of additional tasks.
+     * <ul>
+     *   <li>The stack trace at the point where the method was called will be
+     *       recorded and associated with the returned object.</li>
+     *   <li>The returned object will be wrapped so that the point where 
close()
+     *       (or equivalent) is called to release the resources can be 
detected.
+     *       Tracking of the object will cease once the resources have been
+     *       released.</li>
+     *   <li>All remaining locked resources on web application shutdown will be
+     *       logged and then closed.</li>
+     * </ul>
+     *
+     * @param traceLockedFiles @true to enable it, @false to disable it
+     */
+    void setTraceLockedFiles(boolean traceLockedFiles);
+
+    /**
+     * Has the trace locked files feature been enabled?
+     *
+     * @return @true if it has been enabled, otherwise @false
+     */
+    boolean getTraceLockedFiles();
+
+    /**
      * This method will be invoked by the context on a periodic basis and 
allows
      * the implementation a method that executes periodic tasks, such as 
purging
      * expired cache entries.
@@ -372,4 +399,8 @@ public interface WebResourceRoot extends
         POST,
         CLASSES_JAR
     }
+
+    void registerTracedResource(WebResourceTraceWrapper traceWrapper);
+
+    void deregisterTracedResource(WebResourceTraceWrapper 
traceWrapperInputStream);
 }

Added: tomcat/trunk/java/org/apache/catalina/WebResourceTraceWrapper.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/WebResourceTraceWrapper.java?rev=1538836&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/WebResourceTraceWrapper.java (added)
+++ tomcat/trunk/java/org/apache/catalina/WebResourceTraceWrapper.java Tue Nov  
5 00:06:50 2013
@@ -0,0 +1,24 @@
+/*
+ * 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;
+
+import java.io.Closeable;
+
+public interface WebResourceTraceWrapper extends Closeable {
+    Exception getCreatedBy();
+    String getName();
+}

Modified: 
tomcat/trunk/java/org/apache/catalina/webresources/AbstractResource.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/AbstractResource.java?rev=1538836&r1=1538835&r2=1538836&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/webresources/AbstractResource.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/webresources/AbstractResource.java 
Tue Nov  5 00:06:50 2013
@@ -128,5 +128,19 @@ public abstract class AbstractResource i
     }
 
 
+    @Override
+    public final InputStream getInputStream() {
+        InputStream is = doGetInputStream();
+
+        if (is == null || !root.getTraceLockedFiles()) {
+            return is;
+        }
+
+        return new TraceWrapperInputStream(root, getName(), is);
+    }
+
+    protected abstract InputStream doGetInputStream();
+
+
     protected abstract Log getLog();
 }

Modified: tomcat/trunk/java/org/apache/catalina/webresources/FileResource.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/FileResource.java?rev=1538836&r1=1538835&r2=1538836&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/webresources/FileResource.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/webresources/FileResource.java Tue 
Nov  5 00:06:50 2013
@@ -123,7 +123,7 @@ public class FileResource extends Abstra
     }
 
     @Override
-    public InputStream getInputStream() {
+    protected InputStream doGetInputStream() {
         if (resource.exists()) {
             try {
                 return new FileInputStream(resource);

Modified: tomcat/trunk/java/org/apache/catalina/webresources/JarResource.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/JarResource.java?rev=1538836&r1=1538835&r2=1538836&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/webresources/JarResource.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/webresources/JarResource.java Tue Nov 
 5 00:06:50 2013
@@ -39,7 +39,7 @@ public class JarResource extends Abstrac
     }
 
     @Override
-    public InputStream getInputStream() {
+    protected InputStream doGetInputStream() {
         try {
             JarFile jarFile = new JarFile(getBase());
             InputStream is = jarFile.getInputStream(getResource());

Modified: 
tomcat/trunk/java/org/apache/catalina/webresources/JarResourceRoot.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/JarResourceRoot.java?rev=1538836&r1=1538835&r2=1538836&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/webresources/JarResourceRoot.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/webresources/JarResourceRoot.java Tue 
Nov  5 00:06:50 2013
@@ -104,7 +104,7 @@ public class JarResourceRoot extends Abs
     }
 
     @Override
-    public InputStream getInputStream() {
+    protected InputStream doGetInputStream() {
         return null;
     }
 

Modified: tomcat/trunk/java/org/apache/catalina/webresources/JarWarResource.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/JarWarResource.java?rev=1538836&r1=1538835&r2=1538836&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/webresources/JarWarResource.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/webresources/JarWarResource.java Tue 
Nov  5 00:06:50 2013
@@ -45,7 +45,7 @@ public class JarWarResource extends Abst
     }
 
     @Override
-    public InputStream getInputStream() {
+    protected InputStream doGetInputStream() {
         try {
             JarFile warFile = new JarFile(getBase());
             JarEntry jarFileInWar = warFile.getJarEntry(archivePath);

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=1538836&r1=1538835&r2=1538836&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/webresources/LocalStrings.properties 
(original)
+++ tomcat/trunk/java/org/apache/catalina/webresources/LocalStrings.properties 
Tue Nov  5 00:06:50 2013
@@ -33,6 +33,7 @@ standardRoot.checkStateNotStarted=The re
 standardRoot.createInvalidFile=Unable to create WebResourceSet from [{0}]
 standardRoot.createNoFileResourceSet=The FileResourceSet feature has not yet 
been implemented
 standardRoot.createUnknownType=Unable to create WebResourceSet of unknown type 
[{0}]
+standardRoot.lockedFile=The web application [{0}] failed to close the file 
[{1}] opened via the following stack trace
 standardRoot.noContext=A Context has not been configured for this 
WebResourceRoot
 standardRoot.startInvalidMain=The main resource set specified [{0}] is not 
valid
 standardRoot.unsupportedProtocol=The URL protocol [{0}] is not supported by 
this web resources implementation
\ No newline at end of file

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=1538836&r1=1538835&r2=1538836&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java 
(original)
+++ tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java Tue 
Nov  5 00:06:50 2013
@@ -17,6 +17,7 @@
 package org.apache.catalina.webresources;
 
 import java.io.File;
+import java.io.IOException;
 import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URISyntaxException;
@@ -33,7 +34,10 @@ import org.apache.catalina.LifecycleStat
 import org.apache.catalina.WebResource;
 import org.apache.catalina.WebResourceRoot;
 import org.apache.catalina.WebResourceSet;
+import org.apache.catalina.WebResourceTraceWrapper;
 import org.apache.catalina.util.LifecycleMBeanBase;
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.res.StringManager;
 
 /**
@@ -51,6 +55,7 @@ import org.apache.tomcat.util.res.String
 public class StandardRoot extends LifecycleMBeanBase
         implements WebResourceRoot {
 
+    private static final Log log = LogFactory.getLog(Cache.class);
     protected static final StringManager sm =
             StringManager.getManager(Constants.Package);
 
@@ -65,6 +70,9 @@ public class StandardRoot extends Lifecy
     private Cache cache = new Cache(this);
     private boolean cachingAllowed = true;
 
+    private boolean traceLockedFiles = false;
+    private Set<WebResourceTraceWrapper> tracedResources = new HashSet<>();
+
     // Constructs to make iteration over all WebResourceSets simpler
     private ArrayList<WebResourceSet> mainResources = new ArrayList<>();
     private ArrayList<ArrayList<WebResourceSet>> allResources =
@@ -431,6 +439,16 @@ public class StandardRoot extends Lifecy
     }
 
     @Override
+    public void setTraceLockedFiles(boolean traceLockedFiles) {
+        this.traceLockedFiles = traceLockedFiles;
+    }
+
+    @Override
+    public boolean getTraceLockedFiles() {
+        return traceLockedFiles;
+    }
+
+    @Override
     public Context getContext() {
         return context;
     }
@@ -483,6 +501,19 @@ public class StandardRoot extends Lifecy
         cache.backgroundProcess();
     }
 
+
+    @Override
+    public void registerTracedResource(WebResourceTraceWrapper traceResource) {
+        tracedResources.add(traceResource);
+    }
+
+
+    @Override
+    public void deregisterTracedResource(WebResourceTraceWrapper 
traceResource) {
+        tracedResources.remove(traceResource);
+    }
+
+
     // ----------------------------------------------------------- JMX 
Lifecycle
     @Override
     protected String getDomainInternal() {
@@ -575,6 +606,17 @@ public class StandardRoot extends Lifecy
         }
         jarResources.clear();
 
+        for (WebResourceTraceWrapper tracedResource : tracedResources) {
+            log.error(sm.getString("standardRoot.lockedFile",
+                    context.getName(),
+                    tracedResource.getName()),
+                    tracedResource.getCreatedBy());
+            try {
+                tracedResource.close();
+            } catch (IOException e) {
+                // Ignore
+            }
+        }
         cache.clear();
 
         setState(LifecycleState.STOPPING);

Added: 
tomcat/trunk/java/org/apache/catalina/webresources/TraceWrapperInputStream.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/TraceWrapperInputStream.java?rev=1538836&view=auto
==============================================================================
--- 
tomcat/trunk/java/org/apache/catalina/webresources/TraceWrapperInputStream.java 
(added)
+++ 
tomcat/trunk/java/org/apache/catalina/webresources/TraceWrapperInputStream.java 
Tue Nov  5 00:06:50 2013
@@ -0,0 +1,96 @@
+/*
+ * 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.IOException;
+import java.io.InputStream;
+
+import org.apache.catalina.WebResourceRoot;
+import org.apache.catalina.WebResourceTraceWrapper;
+
+class TraceWrapperInputStream extends InputStream implements 
WebResourceTraceWrapper {
+
+    private final WebResourceRoot root;
+    private final String name;
+    private final InputStream is;
+    private final Exception creation;
+
+    TraceWrapperInputStream(WebResourceRoot root, String name, InputStream is) 
{
+        this.root = root;
+        this.name = name;
+        this.is = is;
+        this.creation = new Exception();
+
+        root.registerTracedResource(this);
+    }
+
+    @Override
+    public int read() throws IOException {
+        return is.read();
+    }
+
+    @Override
+    public int read(byte[] b) throws IOException {
+        return is.read(b);
+    }
+
+    @Override
+    public int read(byte[] b, int off, int len) throws IOException {
+        return is.read(b, off, len);
+    }
+
+    @Override
+    public long skip(long n) throws IOException {
+        return is.skip(n);
+    }
+
+    @Override
+    public int available() throws IOException {
+        return is.available();
+    }
+
+    @Override
+    public void close() throws IOException {
+        root.deregisterTracedResource(this);
+        is.close();
+    }
+
+    @Override
+    public synchronized void mark(int readlimit) {
+        is.mark(readlimit);
+    }
+
+    @Override
+    public synchronized void reset() throws IOException {
+        is.reset();
+    }
+
+    @Override
+    public boolean markSupported() {
+        return is.markSupported();
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public Exception getCreatedBy() {
+        return creation;
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to