Adding cleanup of the javax.servlet.context.tempdir. See bug 158145
- moving servlet.destroy() in ServletRegistration to be done under the correct ContextClassLoader
- adding a serialVersionUID to HttpServiceServlet to cleanup a warning
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/HttpServiceServlet.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/HttpServiceServlet.java
index 28874a0..043e04e 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/HttpServiceServlet.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/HttpServiceServlet.java
@@ -8,5 +8,6 @@
* This class is not meant for extending or even using directly and is purely meant for registering
* in a servlet container.
*/
-public class HttpServiceServlet extends ProxyServlet {
+public class HttpServiceServlet extends ProxyServlet {
+ private static final long serialVersionUID = -3647550992964861187L;
}
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ProxyContext.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ProxyContext.java
index fd3a671..b733162 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ProxyContext.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ProxyContext.java
@@ -1,20 +1,39 @@
package org.eclipse.equinox.http.servlet.internal;
+import java.io.File;
import java.util.*;
+import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.osgi.service.http.HttpContext;
/**
* The ProxyContext provides something similar to a ServletContext for all servlets and resources under a particular ProxyServlet.
* In particular it holds and represent the concept of "context path" through the Proxy Servlets servlet path.
- * The Http Service also requires a ServletContext namespaced by eachindividual HttpContext. The ProxyContext provides support for the
- * attribute map of a ServletContext again namespaced by HttpContext as specified in the Http Service specification. A WeakHashMap is
- * used to hold the various attributes so that when the HttpContext is no longer referenced the associated context attributes can be
- * garbage collected.
+ * The Http Service also requires a ServletContext namespaced by each individual HttpContext. The ProxyContext provides support for the
+ * attribute map of a ServletContext again namespaced by HttpContext as specified in the Http Service specification. The ContextAttributes
+ * are reference counted so that when the HttpContext is no longer referenced the associated context attributes can be
+ * garbage collected and the context temp dir deleteted.
*/
public class ProxyContext {
+ private static final String JAVAX_SERVLET_CONTEXT_TEMPDIR = "javax.servlet.context.tempdir"; //$NON-NLS-1$
+
private String servletPath;
- private WeakHashMap contextAttributes = new WeakHashMap();
+ private HashMap attributesMap = new HashMap();
+ private File proxyContextTempDir;
+
+ public ProxyContext(ServletContext servletContext) {
+ File tempDir = (File) servletContext.getAttribute(JAVAX_SERVLET_CONTEXT_TEMPDIR);
+ if (tempDir != null) {
+ proxyContextTempDir = new File(tempDir, "ProxyContextTemp"); //$NON-NLS-1$
+ deleteDirectory(proxyContextTempDir);
+ proxyContextTempDir.mkdirs();
+ }
+ }
+
+ public void destroy() {
+ if (proxyContextTempDir != null)
+ deleteDirectory(proxyContextTempDir);
+ }
synchronized void initializeServletPath(HttpServletRequest req) {
if (servletPath == null)
@@ -26,11 +45,74 @@
}
synchronized void createContextAttributes(HttpContext httpContext) {
- if (!contextAttributes.containsKey(httpContext))
- contextAttributes.put(httpContext, new Hashtable());
+ ContextAttributes attributes = (ContextAttributes) attributesMap.get(httpContext);
+ if (attributes == null) {
+ attributes = new ContextAttributes(httpContext);
+ attributesMap.put(httpContext, attributes);
+ }
+ attributes.addReference();
}
+ synchronized void destroyContextAttributes(HttpContext httpContext) {
+ ContextAttributes attributes = (ContextAttributes) attributesMap.get(httpContext);
+ attributes.removeReference();
+ if (attributes.referenceCount() == 0) {
+ attributesMap.remove(httpContext);
+ attributes.destroy();
+ }
+ }
+
synchronized Dictionary getContextAttributes(HttpContext httpContext) {
- return (Dictionary) contextAttributes.get(httpContext);
+ return (Dictionary) attributesMap.get(httpContext);
+ }
+
+ /**
+ * deleteDirectory is a convenience method to recursively delete a directory
+ * @param directory - the directory to delete.
+ * @return was the delete succesful
+ */
+ protected static boolean deleteDirectory(File directory) {
+ if (directory.exists() && directory.isDirectory()) {
+ File[] files = directory.listFiles();
+ for (int i = 0; i < files.length; i++) {
+ if (files[i].isDirectory()) {
+ deleteDirectory(files[i]);
+ } else {
+ files[i].delete();
+ }
+ }
+ }
+ return directory.delete();
+ }
+
+ public class ContextAttributes extends Hashtable {
+ private static final long serialVersionUID = 1916670423277243587L;
+ private int referenceCount;
+
+ public ContextAttributes(HttpContext httpContext) {
+ if (proxyContextTempDir != null) {
+ File contextTempDir = new File(proxyContextTempDir, "HttpContext" + httpContext.hashCode()); //$NON-NLS-1$
+ contextTempDir.mkdirs();
+ put(JAVAX_SERVLET_CONTEXT_TEMPDIR, contextTempDir);
+ }
+ }
+
+ public void destroy() {
+ File contextTempDir = (File) get(JAVAX_SERVLET_CONTEXT_TEMPDIR);
+ if (contextTempDir != null)
+ deleteDirectory(contextTempDir);
+ }
+
+ public void addReference() {
+ referenceCount++;
+ }
+
+ public void removeReference() {
+ referenceCount--;
+ }
+
+ public int referenceCount() {
+ return referenceCount;
+ }
}
}
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ProxyServlet.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ProxyServlet.java
index dc7dac2..638cd7b 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ProxyServlet.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ProxyServlet.java
@@ -36,12 +36,13 @@
public void init(ServletConfig config) throws ServletException {
super.init(config);
- proxyContext = new ProxyContext();
+ proxyContext = new ProxyContext(config.getServletContext());
Activator.addProxyServlet(this);
}
public void destroy() {
Activator.removeProxyServlet(this);
+ proxyContext.destroy();
proxyContext = null;
super.destroy();
}
@@ -131,7 +132,7 @@
if (servlet == null)
throw new IllegalArgumentException("Servlet cannot be null"); //$NON-NLS-1$
- ServletRegistration registration = new ServletRegistration(servlet, context, bundle, servlets);
+ ServletRegistration registration = new ServletRegistration(servlet, proxyContext, context, bundle, servlets);
registration.checkServletRegistration();
ServletContext wrappedServletContext = new ServletContextAdaptor(proxyContext, getServletContext(), context, AccessController.getContext());
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ServletContextAdaptor.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ServletContextAdaptor.java
index 0d2bb43..c69f6d7 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ServletContextAdaptor.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ServletContextAdaptor.java
@@ -21,7 +21,6 @@
public class ServletContextAdaptor implements ServletContext {
- private static final String JAVAX_SERVLET_CONTEXT_TEMPDIR = "javax.servlet.context.tempdir"; //$NON-NLS-1$
private ServletContext servletContext;
HttpContext httpContext;
private AccessControlContext acc;
@@ -32,17 +31,6 @@
this.httpContext = httpContext;
this.acc = acc;
this.proxyContext = proxyContext;
- proxyContext.createContextAttributes(httpContext);
-
- if (proxyContext.getContextAttributes(httpContext).get(JAVAX_SERVLET_CONTEXT_TEMPDIR) == null) {
- File tempDir = (File) servletContext.getAttribute(JAVAX_SERVLET_CONTEXT_TEMPDIR);
- if (tempDir != null) {
- File contextTempDir = new File(tempDir, "HttpContext" + httpContext.hashCode()); //$NON-NLS-1$
- contextTempDir.mkdirs();
- contextTempDir.deleteOnExit();
- proxyContext.getContextAttributes(httpContext).put(JAVAX_SERVLET_CONTEXT_TEMPDIR, contextTempDir);
- }
- }
}
/**
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ServletRegistration.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ServletRegistration.java
index 4c08a9f..834cbe7 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ServletRegistration.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/ServletRegistration.java
@@ -28,11 +28,13 @@
private HttpContext httpContext; //The context used during the registration of the servlet
private Set servlets; //All the servlets registered against the instance of the proxy servlet that "ownes" self.
private ClassLoader registeredContextClassLoader;
+ private ProxyContext proxyContext;
- public ServletRegistration(Servlet servlet, HttpContext context, Bundle bundle, Set servlets) {
+ public ServletRegistration(Servlet servlet, ProxyContext proxyContext, HttpContext context, Bundle bundle, Set servlets) {
this.servlet = servlet;
this.servlets = servlets;
this.httpContext = context;
+ this.proxyContext = proxyContext;
registeredContextClassLoader = Thread.currentThread().getContextClassLoader();
}
@@ -41,26 +43,35 @@
try {
Thread.currentThread().setContextClassLoader(registeredContextClassLoader);
super.destroy();
+ servlet.destroy();
} finally {
Thread.currentThread().setContextClassLoader(original);
- }
- servlet.destroy();
+ }
}
- public void close() {
+ public void close() {
servlets.remove(servlet);
+ proxyContext.destroyContextAttributes(httpContext);
}
//Delegate the init call to the actual servlet
public void init(ServletConfig servletConfig) throws ServletException {
- ClassLoader original = Thread.currentThread().getContextClassLoader();
+ boolean initialized = false;
+ proxyContext.createContextAttributes(httpContext);
try {
- Thread.currentThread().setContextClassLoader(registeredContextClassLoader);
- servlet.init(servletConfig);
+ ClassLoader original = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(registeredContextClassLoader);
+ servlet.init(servletConfig);
+ } finally {
+ Thread.currentThread().setContextClassLoader(original);
+ }
+ servlets.add(servlet);
+ initialized = true;
} finally {
- Thread.currentThread().setContextClassLoader(original);
+ if (! initialized)
+ proxyContext.destroyContextAttributes(httpContext);
}
- servlets.add(servlet);
}
public void checkServletRegistration() throws ServletException {