Bug 547270 - [Http] Create and register a ServletContextHelper for the
default HttpContext for each bundle

Change-Id: I0bea6492f7e8ef3649d619893b7cac9d5cdff096
Signed-off-by: Anjum Fatima <anjum.eclipse@gmail.com>
Signed-off-by: Thomas Watson <tjwatson@us.ibm.com>
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/HttpServiceImpl.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/HttpServiceImpl.java
index 304ab23..4913da3 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/HttpServiceImpl.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/HttpServiceImpl.java
@@ -54,12 +54,7 @@
 	public synchronized HttpContext createDefaultHttpContext() {
 		checkShutdown();
 
-		DefaultServletContextHelper defaultServletContextHelper = bundle.getBundleContext().getService(httpServiceRuntime.defaultContextReg.getReference());
-		HttpContextHolder httpContextHolder = new HttpContextHolder(defaultServletContextHelper, httpServiceRuntime.defaultContextReg);
-		httpContextHolder.incrementUseCount();
-		httpServiceRuntime.legacyContextMap.putIfAbsent(defaultServletContextHelper, httpContextHolder);
-
-		return defaultServletContextHelper;
+		return new DefaultServletContextHelper(bundle);
 	}
 
 	/**
@@ -74,8 +69,8 @@
 		throws ServletException {
 
 		checkShutdown();
-		httpContext = httpContext == null ? createDefaultHttpContext() : registerContext(httpContext);
-		final HttpContextHolder httpContextHolder = httpServiceRuntime.legacyContextMap.get(httpContext);
+		
+		final HttpContextHolder httpContextHolder = getHttpContextHolder(httpContext);
 		try {
 			AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
 				@Override
@@ -91,6 +86,14 @@
 
 	}
 
+	private HttpContextHolder getHttpContextHolder(HttpContext httpContext) {
+		if (httpContext == null) {
+			httpContext = createDefaultHttpContext();
+		}
+		registerContext(httpContext);
+		return httpServiceRuntime.legacyContextMap.get(httpContext);
+	}
+
 	/**
 	 * @throws NamespaceException
 	 * @see HttpService#registerResources(String, String, HttpContext)
@@ -100,8 +103,7 @@
 		throws NamespaceException {
 
 		checkShutdown();
-		httpContext = httpContext == null ? createDefaultHttpContext() : registerContext(httpContext);
-		final HttpContextHolder httpContextHolder = httpServiceRuntime.legacyContextMap.get(httpContext);
+		final HttpContextHolder httpContextHolder = getHttpContextHolder(httpContext);
 		try {
 			AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
 				@Override
@@ -127,8 +129,7 @@
 		throws ServletException, NamespaceException {
 
 		checkShutdown();
-		httpContext = httpContext == null ? createDefaultHttpContext() : registerContext(httpContext);
-		final HttpContextHolder httpContextHolder = httpServiceRuntime.legacyContextMap.get(httpContext);
+		final HttpContextHolder httpContextHolder = getHttpContextHolder(httpContext);
 		try {
 			AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
 				@Override
@@ -183,7 +184,7 @@
 		HttpContextHolder httpContextHolder = httpServiceRuntime.legacyContextMap.get(httpContext);
 
 		if (httpContextHolder == null) {
-			String legacyId = httpContext.getClass().getName().replaceAll("[^a-zA-Z_0-9\\-]", "_") + "-" + generateLegacyId(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+			String legacyId= httpContext.getClass().getName().replaceAll("[^a-zA-Z_0-9\\-]", "_") + "-" + generateLegacyId(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 			Dictionary<String, Object> props = new Hashtable<String, Object>();
 			props.put(HTTP_WHITEBOARD_CONTEXT_NAME, legacyId);
 			props.put(HTTP_WHITEBOARD_CONTEXT_PATH, "/"); //$NON-NLS-1$
@@ -198,6 +199,8 @@
 			httpContextHolder.incrementUseCount();
 
 			httpServiceRuntime.legacyContextMap.put(httpContext, httpContextHolder);
+		} else {
+			httpContextHolder.incrementUseCount();
 		}
 
 		return httpContext;
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/HttpServiceRuntimeImpl.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/HttpServiceRuntimeImpl.java
index ecd7b2c..c0e9df3 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/HttpServiceRuntimeImpl.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/HttpServiceRuntimeImpl.java
@@ -57,7 +57,6 @@
 		HttpServiceRuntime,
 		ServiceTrackerCustomizer<ServletContextHelper, AtomicReference<ContextController>> {
 
-	@SuppressWarnings("unchecked")
 	public HttpServiceRuntimeImpl(
 		BundleContext trackingContext, BundleContext consumingContext,
 		ServletContext parentServletContext, Dictionary<String, Object> attributes) {
@@ -110,9 +109,9 @@
 		defaultContextProps.put(Constants.SERVICE_RANKING, Integer.MIN_VALUE);
 		defaultContextProps.put(HTTP_WHITEBOARD_CONTEXT_PATH, Const.SLASH);
 		defaultContextProps.put(HTTP_WHITEBOARD_TARGET, this.targetFilter);
-		defaultContextProps.put(HTTP_SERVICE_CONTEXT_PROPERTY, HTTP_WHITEBOARD_DEFAULT_CONTEXT_NAME);
-		defaultContextReg = (ServiceRegistration<DefaultServletContextHelper>) consumingContext.registerService(
-			new String [] {ServletContextHelper.class.getName(), DefaultServletContextHelper.class.getName()}, new DefaultServletContextHelperFactory(), defaultContextProps);
+		defaultContextProps.put(Const.EQUINOX_HTTP_WHITEBOARD_CONTEXT_HELPER_DEFAULT, Boolean.TRUE);
+		defaultContextReg = consumingContext.registerService(
+			ServletContextHelper.class, new DefaultServletContextHelperFactory(), defaultContextProps);
 	}
 
 	public synchronized void open() {
@@ -689,7 +688,8 @@
 				props.put(HTTP_WHITEBOARD_TARGET, targetFilter);
 				props.put(HTTP_WHITEBOARD_FILTER_PATTERN, alias);
 				props.put(HTTP_WHITEBOARD_FILTER_NAME, filterName);
-				props.put(HTTP_WHITEBOARD_CONTEXT_SELECT, getFilter(httpContextHolder.getServiceReference()));
+				props.put(HTTP_WHITEBOARD_CONTEXT_SELECT, "(" + Const.EQUINOX_LEGACY_CONTEXT_HELPER + "=true)"); //$NON-NLS-1$ //$NON-NLS-2$
+				props.put(Const.EQUINOX_LEGACY_CONTEXT_SELECT, getFilter(httpContextHolder.getServiceReference()));
 				props.put(Const.EQUINOX_LEGACY_TCCL_PROP, Thread.currentThread().getContextClassLoader());
 				props.put(Constants.SERVICE_RANKING, findFilterPriority(initparams));
 				fillInitParams(props, initparams, HTTP_WHITEBOARD_FILTER_INIT_PARAM_PREFIX);
@@ -700,7 +700,6 @@
 
 				// check that init got called and did not throw an exception
 				filterFactory.checkForError();
-				httpContextHolder.incrementUseCount();
 
 				objectRegistration = new HttpServiceObjectRegistration(filter, registration, httpContextHolder, bundle);
 				Set<HttpServiceObjectRegistration> objectRegistrations = bundleRegistrations.get(bundle);
@@ -802,7 +801,6 @@
 				props.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE);
 				props.put(Const.EQUINOX_LEGACY_TCCL_PROP, Thread.currentThread().getContextClassLoader());
 				registration = bundle.getBundleContext().registerService(String.class, "resource", props); //$NON-NLS-1$
-				httpContextHolder.incrementUseCount();
 
 				objectRegistration = new HttpServiceObjectRegistration(fullAlias, registration, httpContextHolder, bundle);
 
@@ -891,7 +889,6 @@
 
 				// check that init got called and did not throw an exception
 				legacyServlet.checkForError();
-				httpContextHolder.incrementUseCount();
 
 				objectRegistration = new HttpServiceObjectRegistration(fullAlias, registration, httpContextHolder, bundle);
 
@@ -1284,7 +1281,7 @@
 
 	private final Map<String, Object> attributes;
 	private final String targetFilter;
-	final ServiceRegistration<DefaultServletContextHelper> defaultContextReg;
+	final ServiceRegistration<ServletContextHelper> defaultContextReg;
 	private final ServletContext parentServletContext;
 	private final BundleContext trackingContext;
 	private final BundleContext consumingContext;
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/ContextController.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/ContextController.java
index 7b131d7..093e2b8 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/ContextController.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/ContextController.java
@@ -905,6 +905,12 @@
 	}
 
 	private boolean visibleContextHelper(ServiceReference<?> whiteBoardService) {
+		if (consumingContext.getBundle().equals(serviceReference.getBundle())) {
+			Boolean defaultContextHelper = (Boolean) serviceReference.getProperty(Const.EQUINOX_HTTP_WHITEBOARD_CONTEXT_HELPER_DEFAULT);
+			if (defaultContextHelper == null) {
+				return true;
+			}
+		}
 		try {
 			if (whiteBoardService.getBundle().getBundleContext().getAllServiceReferences(ServletContextHelper.class.getName(), servletContextHelperRefFilter) != null) {
 				return true;
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/FilterRegistration.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/FilterRegistration.java
index e3e5dcd..491305a 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/FilterRegistration.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/FilterRegistration.java
@@ -25,6 +25,8 @@
 import org.eclipse.equinox.http.servlet.internal.servlet.FilterChainImpl;
 import org.eclipse.equinox.http.servlet.internal.servlet.Match;
 import org.eclipse.equinox.http.servlet.internal.util.Const;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.wiring.BundleWiring;
 import org.osgi.service.http.runtime.dto.FilterDTO;
 
@@ -56,7 +58,22 @@
 		} else {
 			classLoader = filterHolder.getBundle().adapt(BundleWiring.class).getClassLoader();
 		}
-		initDestoyWithContextController = true;
+		String legacyContextFilter = (String) filterHolder.getServiceReference().getProperty(Const.EQUINOX_LEGACY_CONTEXT_SELECT);
+		if (legacyContextFilter != null) {
+			// This is a legacy Filter registration.  
+			// This filter tells us the real context controller,
+			// backed by an HttpContext that should be used to init/destroy this Filter
+			org.osgi.framework.Filter f = null;
+			try {
+				f = FrameworkUtil.createFilter(legacyContextFilter);
+			}
+			catch (InvalidSyntaxException e) {
+				// nothing
+			}
+			initDestoyWithContextController = f == null || contextController.matches(f);
+		} else {
+			initDestoyWithContextController = true;
+		}
 		needDecode = MatchableRegistration.patternsRequireDecode(filterDTO.patterns);
 	}
 
diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/util/Const.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/util/Const.java
index 2a725ff..95367b1 100644
--- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/util/Const.java
+++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/util/Const.java
@@ -48,8 +48,10 @@
 	public static final String EQUINOX_HTTP_MULTIPART_MAXFILESIZE = "equinox.http.whiteboard.servlet.multipart.maxFileSize"; //$NON-NLS-1$
 	public static final String EQUINOX_HTTP_MULTIPART_MAXREQUESTSIZE = "equinox.http.whiteboard.servlet.multipart.maxRequestSize"; //$NON-NLS-1$
 	public static final String EQUINOX_LEGACY_TCCL_PROP = "equinox.legacy.tccl"; //$NON-NLS-1$
+	public static final String EQUINOX_LEGACY_CONTEXT_SELECT = "equinox.context.select"; //$NON-NLS-1$
 	public static final String EQUINOX_LEGACY_CONTEXT_HELPER = "equinox.legacy.context.helper"; //$NON-NLS-1$
 	public static final String EQUINOX_LEGACY_HTTP_CONTEXT_INITIATING_ID = "equinox.legacy.http.context.initiating.id"; //$NON-NLS-1$
+	public static final String EQUINOX_HTTP_WHITEBOARD_CONTEXT_HELPER_DEFAULT = "equinox.http.whiteboard.context.helper.default"; //$NON-NLS-1$
 	public static final String UTF8 = "UTF-8"; //$NON-NLS-1$
 
 }