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 {