/*******************************************************************************
 * Copyright (c) 2014, 2015 Raymond Augé and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Raymond Augé <raymond.auge@liferay.com> - Bug 436698
 ******************************************************************************/

package org.eclipse.equinox.http.servlet.internal;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import javax.servlet.*;
import javax.servlet.Filter;
import javax.servlet.http.*;
import org.eclipse.equinox.http.servlet.context.ContextPathCustomizer;
import org.eclipse.equinox.http.servlet.internal.context.*;
import org.eclipse.equinox.http.servlet.internal.error.*;
import org.eclipse.equinox.http.servlet.internal.servlet.*;
import org.eclipse.equinox.http.servlet.internal.util.*;
import org.osgi.framework.*;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.NamespaceException;
import org.osgi.service.http.context.ServletContextHelper;
import org.osgi.service.http.runtime.HttpServiceRuntime;
import org.osgi.service.http.runtime.HttpServiceRuntimeConstants;
import org.osgi.service.http.runtime.dto.*;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;

/**
 * @author Raymond Augé
 */
public class HttpServiceRuntimeImpl
	implements
		HttpServiceRuntime,
		ServiceTrackerCustomizer<ServletContextHelper, AtomicReference<ContextController>> {

	public HttpServiceRuntimeImpl(
		BundleContext trackingContext, BundleContext consumingContext,
		ServletContext parentServletContext, Map<String, Object> attributes) {

		this.trackingContext = trackingContext;
		this.consumingContext = consumingContext;

		this.servletServiceFilter = createServletFilter(consumingContext);
		this.resourceServiceFilter = createResourceFilter(consumingContext);
		this.filterServiceFilter = createFilterFilter(consumingContext);
		this.listenerServiceFilter = createListenerFilter(consumingContext);

		this.parentServletContext = parentServletContext;
		this.attributes = Collections.unmodifiableMap(attributes);
		this.targetFilter = "(" + Activator.UNIQUE_SERVICE_ID + "=" + attributes.get(Activator.UNIQUE_SERVICE_ID) + ")";  //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

		contextServiceTracker =
			new ServiceTracker<ServletContextHelper, AtomicReference<ContextController>>(
				trackingContext, ServletContextHelper.class, this);

		contextPathCustomizerHolder = new ContextPathCustomizerHolder(consumingContext, contextServiceTracker);
		contextPathAdaptorTracker = new ServiceTracker<ContextPathCustomizer, ContextPathCustomizer>(
			consumingContext, ContextPathCustomizer.class, contextPathCustomizerHolder);
		contextPathAdaptorTracker.open();

		contextServiceTracker.open();

		Hashtable<String, Object> defaultContextProps = new Hashtable<String, Object>();
		defaultContextProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, HttpWhiteboardConstants.HTTP_WHITEBOARD_DEFAULT_CONTEXT_NAME);
		defaultContextProps.put(Constants.SERVICE_RANKING, Integer.MIN_VALUE);
		defaultContextProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, Const.SLASH);
		defaultContextProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_TARGET, this.targetFilter);
		defaultContextReg = consumingContext.registerService(ServletContextHelper.class, new DefaultServletContextHelperFactory(), defaultContextProps);
	}

	@Override
	public synchronized AtomicReference<ContextController> addingService(
		ServiceReference<ServletContextHelper> serviceReference) {

		AtomicReference<ContextController> result = new AtomicReference<ContextController>();
		if (!matches(serviceReference)) {
			return result;
		}

		String contextName = (String)serviceReference.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME);
		String contextPath = (String)serviceReference.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH);

		try {
			if (contextName == null) {
				throw new IllegalContextNameException(
					HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + " is null. Ignoring!", //$NON-NLS-1$
					DTOConstants.FAILURE_REASON_VALIDATION_FAILED);
			}

			if (contextPath == null) {
				throw new IllegalContextPathException(
					HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH + " is null. Ignoring!", //$NON-NLS-1$
					DTOConstants.FAILURE_REASON_VALIDATION_FAILED);
			}

			contextPath = adaptContextPath(contextPath, serviceReference);

			ContextController contextController = new ContextController(
				trackingContext, consumingContext, serviceReference, new ProxyContext(parentServletContext),
				this, contextName, contextPath);

			controllerMap.put(serviceReference, contextController);

			result.set(contextController);
		}
		catch (HttpWhiteboardFailureException hwfe) {
			parentServletContext.log(hwfe.getMessage(), hwfe);

			recordFailedServletContextDTO(serviceReference, contextName, contextPath, hwfe.getFailureReason());
		}
		catch (Exception e) {
			parentServletContext.log(e.getMessage(), e);

			recordFailedServletContextDTO(serviceReference, contextName, contextPath, DTOConstants.FAILURE_REASON_EXCEPTION_ON_INIT);
		}

		return result;
	}

	private String adaptContextPath(String contextPath, ServiceReference<ServletContextHelper> helper) {
		ContextPathCustomizer pathAdaptor = contextPathCustomizerHolder.getHighestRanked();
		if (pathAdaptor != null) {
			String contextPrefix = pathAdaptor.getContextPathPrefix(helper);
			if (contextPrefix != null && !contextPrefix.isEmpty() && !contextPrefix.equals(Const.SLASH)) {
				if (!contextPrefix.startsWith(Const.SLASH)) {
					contextPrefix = Const.SLASH + contextPrefix;
				}
				return contextPrefix + contextPath;
			}
		}
		return contextPath;
	}

	public String getDefaultContextSelectFilter(ServiceReference<?> httpWhiteBoardService) {
		ContextPathCustomizer pathAdaptor = contextPathCustomizerHolder.getHighestRanked();
		if (pathAdaptor != null) {
			return pathAdaptor.getDefaultContextSelectFilter(httpWhiteBoardService);
		}
		return null;
	}

	@Override
	public RequestInfoDTO calculateRequestInfoDTO(String path) {
		RequestInfoDTO requestInfoDTO = new RequestInfoDTO();

		requestInfoDTO.path = path;

		try {
			doDispatch(null, null, path, requestInfoDTO);
		}
		catch (Exception e) {
			throw new RuntimeException(e);
		}

		return requestInfoDTO;
	}

	public void destroy() {
		defaultContextReg.unregister();

		contextServiceTracker.close();
		contextPathAdaptorTracker.close();

		controllerMap.clear();
		registeredObjects.clear();

		failedListenerDTOs.clear();
		failedServletContextDTOs.clear();

		attributes = null;
		trackingContext = null;
		consumingContext = null;
		legacyIdGenerator = null;
		parentServletContext = null;
		registeredObjects = null;
		contextServiceTracker = null;
		contextPathCustomizerHolder = null;
	}

	public boolean doDispatch(
			HttpServletRequest request, HttpServletResponse response,
			String path)
		throws ServletException, IOException {

		return doDispatch(request, response, path, null);
	}

	public Set<Object> getRegisteredObjects() {
		return registeredObjects;
	}

	public List<String> getHttpServiceEndpoints() {
		return StringPlus.from(
			attributes.get(
				HttpServiceRuntimeConstants.HTTP_SERVICE_ENDPOINT_ATTRIBUTE));
	}

	@Override
	public RuntimeDTO getRuntimeDTO() {
		RuntimeDTO runtimeDTO = new RuntimeDTO();

		runtimeDTO.attributes = serializeAttributes();

		// TODO

		runtimeDTO.failedErrorPageDTOs = null;
		runtimeDTO.failedFilterDTOs = null;
		runtimeDTO.failedListenerDTOs = getFailedListenerDTOs();
		runtimeDTO.failedResourceDTOs = null;
		runtimeDTO.failedServletContextDTOs = getFailedServletContextDTO();
		runtimeDTO.failedServletDTOs = null;
		runtimeDTO.servletContextDTOs = getServletContextDTOs();

		return runtimeDTO;
	}

	public void log(String message, Throwable t) {
		parentServletContext.log(message, t);
	}

	public boolean matches(ServiceReference<?> serviceReference) {
		String target = (String)serviceReference.getProperty(
			HttpWhiteboardConstants.HTTP_WHITEBOARD_TARGET);

		if (target == null) {
			return true;
		}

		org.osgi.framework.Filter targetFilter;

		try {
			targetFilter = FrameworkUtil.createFilter(target);
		}
		catch (InvalidSyntaxException ise) {
			throw new IllegalArgumentException(ise);
		}

		if (targetFilter.matches(attributes)) {
			return true;
		}

		return false;
	}

	@Override
	public synchronized void modifiedService(
		ServiceReference<ServletContextHelper> serviceReference,
		AtomicReference<ContextController> contextController) {

		removedService(serviceReference, contextController);
		AtomicReference<ContextController> added = addingService(serviceReference);
		contextController.set(added.get());
	}

	@Override
	public synchronized void removedService(
		ServiceReference<ServletContextHelper> serviceReference,
		AtomicReference<ContextController> contextControllerRef) {

		ContextController contextController = contextControllerRef.get();
		if (contextController != null) {
			contextController.destroy();
		}
		controllerMap.remove(serviceReference);
		failedServletContextDTOs.remove(serviceReference);
		trackingContext.ungetService(serviceReference);
	}

	Collection<ContextController> getContextControllers(String requestURI) {
		int pos = requestURI.lastIndexOf('/');

		do {
			List<ContextController> contextControllers = new ArrayList<ContextController>();

			for (ContextController contextController : controllerMap.values()) {
				if (contextController.getContextPath().equals(requestURI)) {
					contextControllers.add(contextController);
				}
			}

			if (!contextControllers.isEmpty()) {
				return contextControllers;
			}

			if (pos > -1) {
				requestURI = requestURI.substring(0, pos);
				pos = requestURI.lastIndexOf('/');

				continue;
			}

			break;
		}
		while (true);

		return null;
	}

	long generateLegacyId() {
		return legacyIdGenerator.getAndIncrement();
	}

	private boolean doDispatch(
			HttpServletRequest request, HttpServletResponse response,
			String path, RequestInfoDTO requestInfoDTO)
		throws ServletException, IOException {

		// perfect match
		if (doDispatch(
				request, response, path, null, Match.EXACT, requestInfoDTO)) {

			return true;
		}

		String extensionAlias = findExtensionAlias(path);

		// extension match
		if (doDispatch(
				request, response, path, extensionAlias, Match.EXTENSION,
				requestInfoDTO)) {

			return true;
		}

		// regex match
		if (doDispatch(
				request, response, path, null, Match.REGEX, requestInfoDTO)) {

			return true;
		}

		// handle '/' aliases
		if (doDispatch(
				request, response, path, null, Match.DEFAULT_SERVLET,
				requestInfoDTO)) {

			return true;
		}

		return false;
	}

	private boolean doDispatch(
			HttpServletRequest request, HttpServletResponse response,
			String requestURI, String extension, Match match,
			RequestInfoDTO requestInfoDTO)
		throws ServletException, IOException {

		DispatchTargets dispatchTargets = getDispatchTargets(
			request, requestURI, extension, match, requestInfoDTO);

		if ((dispatchTargets == null) || (requestInfoDTO != null)) {
			return false;
		}

		ContextController contextController =
			dispatchTargets.getContextController();
		DispatcherType dispatcherType = DispatcherType.REQUEST;

		if (request.getAttribute(RequestDispatcher.INCLUDE_REQUEST_URI) != null) {
			request.setAttribute(RequestDispatcher.INCLUDE_CONTEXT_PATH, contextController.getContextPath());
			request.setAttribute(RequestDispatcher.INCLUDE_PATH_INFO, dispatchTargets.getPathInfo());
			request.setAttribute(RequestDispatcher.INCLUDE_QUERY_STRING, request.getQueryString());
			request.setAttribute(RequestDispatcher.INCLUDE_REQUEST_URI, requestURI);
			request.setAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH, dispatchTargets.getServletPath());

			dispatcherType = DispatcherType.INCLUDE;
		}

		HttpServletRequest wrappedRequest = new HttpServletRequestBuilder(
			request, dispatchTargets).build();
		HttpServletResponseWrapper wrapperResponse =
			new HttpServletResponseWrapperImpl(response);

		ResponseStateHandler responseStateHandler = new ResponseStateHandler(
			wrappedRequest, wrapperResponse, dispatchTargets, dispatcherType);

		responseStateHandler.processRequest();

		return true;
	}

	private String findExtensionAlias(String alias) {
		String lastSegment = alias.substring(alias.lastIndexOf('/') + 1);

		int dot = lastSegment.lastIndexOf('.');

		if (dot == -1) {
			return null;
		}

		return lastSegment.substring(dot + 1);
	}

	private DispatchTargets getDispatchTargets(
		HttpServletRequest request, String requestURI, String extension,
		Match match, RequestInfoDTO requestInfoDTO) {

		Collection<ContextController> contextControllers = getContextControllers(
			requestURI);

		if ((contextControllers == null) || contextControllers.isEmpty()) {
			return null;
		}

		String contextPath =
			contextControllers.iterator().next().getContextPath();

		requestURI = requestURI.substring(contextPath.length());

		int pos = requestURI.lastIndexOf('/');

		String servletPath = requestURI;
		String pathInfo = null;

		if (match == Match.DEFAULT_SERVLET) {
			pathInfo = servletPath;
			servletPath = Const.SLASH;
		}

		do {
			for (ContextController contextController : contextControllers) {
				DispatchTargets dispatchTargets =
					contextController.getDispatchTargets(
						request, null, requestURI, servletPath, pathInfo,
						extension, match, requestInfoDTO);

				if (dispatchTargets != null) {
					return dispatchTargets;
				}
			}

			if ((match == Match.EXACT) || (extension != null)) {
				break;
			}

			if (pos > -1) {
				String newServletPath = requestURI.substring(0, pos);
				pathInfo = requestURI.substring(pos);
				servletPath = newServletPath;
				pos = servletPath.lastIndexOf('/');

				continue;
			}

			break;
		}
		while (true);

		return null;
	}

	private FailedListenerDTO[] getFailedListenerDTOs() {
		Collection<FailedListenerDTO> flDTOs = failedListenerDTOs.values();

		List<FailedListenerDTO> copies = new ArrayList<FailedListenerDTO>();

		for (FailedListenerDTO failedListenerDTO : flDTOs) {
			copies.add(DTOUtil.clone(failedListenerDTO));
		}

		return copies.toArray(new FailedListenerDTO[copies.size()]);
	}

	private FailedServletContextDTO[] getFailedServletContextDTO() {
		Collection<FailedServletContextDTO> fscDTOs = failedServletContextDTOs.values();

		List<FailedServletContextDTO> copies = new ArrayList<FailedServletContextDTO>();

		for (FailedServletContextDTO failedServletContextDTO : fscDTOs) {
			copies.add(DTOUtil.clone(failedServletContextDTO));
		}

		return copies.toArray(new FailedServletContextDTO[copies.size()]);
	}

	private ServletContextDTO[] getServletContextDTOs() {
		List<ServletContextDTO> servletContextDTOs =
			new ArrayList<ServletContextDTO>();

		for (ContextController contextController : controllerMap.values()) {
			servletContextDTOs.add(contextController.getServletContextDTO());
		}

		return servletContextDTOs.toArray(
			new ServletContextDTO[servletContextDTOs.size()]);
	}

	private Map<String, String> serializeAttributes() {
		Map<String, String> temp = new HashMap<String, String>();

		for (Map.Entry<String, Object> entry : attributes.entrySet()) {
			temp.put(entry.getKey(), String.valueOf(entry.getValue()));
		}

		return temp;
	}


	public void registerHttpServiceFilter(
		Bundle bundle, String alias, Filter filter, Dictionary<String, String> initparams, HttpContext httpContext) throws ServletException {

		if (alias == null) {
			throw new IllegalArgumentException("Alias cannot be null");
		}
		if (filter == null) {
			throw new IllegalArgumentException("Filter cannot be null");
		}

		ContextController.checkPattern(alias);

		synchronized (legacyMappings) {
			if (getRegisteredObjects().contains(filter)) {
				throw new RegisteredFilterException(filter);
			}
			HttpServiceObjectRegistration existing = legacyMappings.get(filter);
			if (existing != null) {
				throw new RegisteredFilterException(filter);
			}
			String filterName = filter.getClass().getName();
			if ((initparams != null) && (initparams.get(Const.FILTER_NAME) != null)) {
				filterName = initparams.get(Const.FILTER_NAME);
			}
			HttpContextHelperFactory factory = getOrRegisterHttpContextHelperFactory(bundle, httpContext);

			HttpServiceObjectRegistration objectRegistration = null;
			ServiceRegistration<Filter> registration = null;
			try {
				Dictionary<String, Object> props = new Hashtable<String, Object>();
				props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_TARGET, targetFilter);
				props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN, alias);
				props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_NAME, filterName);
				props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, "(" + Const.EQUINOX_LEGACY_CONTEXT_HELPER + "=true)"); //$NON-NLS-1$ //$NON-NLS-2$
				props.put(Const.EQUINOX_LEGACY_CONTEXT_SELECT, factory.getFilter());
				props.put(Const.EQUINOX_LEGACY_REGISTRATION_PROP, Boolean.TRUE);
				props.put(Constants.SERVICE_RANKING, findFilterPriority(initparams));
				fillInitParams(props, initparams, HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_INIT_PARAM_PREFIX);

				LegacyFilterFactory filterFactory = new LegacyFilterFactory(filter);
				registration = bundle.getBundleContext().registerService(Filter.class, filterFactory, props);

				// check that init got called and did not throw an exception
				filterFactory.checkForError();

				objectRegistration = new HttpServiceObjectRegistration(filter, registration, factory, bundle);
				Set<HttpServiceObjectRegistration> objectRegistrations = bundleRegistrations.get(bundle);
				if (objectRegistrations == null) {
					objectRegistrations = new HashSet<HttpServiceObjectRegistration>();
					bundleRegistrations.put(bundle, objectRegistrations);
				}
				objectRegistrations.add(objectRegistration);
				legacyMappings.put(objectRegistration.serviceKey, objectRegistration);
			} finally {
				if (objectRegistration == null || !legacyMappings.containsKey(objectRegistration.serviceKey)) {
					// something bad happened above (likely going to throw a runtime exception)
					// need to clean up the factory reference
					decrementFactoryUseCount(factory);
					if (registration != null) {
						registration.unregister();
					}
				}
			}
		}
	}

	private void fillInitParams(
		Dictionary<String, Object> props,
		Dictionary<String, String> initparams, String prefix) {
		if (initparams != null) {
			for (Enumeration<String> eKeys = initparams.keys(); eKeys.hasMoreElements();) {
				String key = eKeys.nextElement();
				String value = initparams.get(key);
				if (value != null) {
					props.put(prefix + key, value);
				}
			}
		}
	}

	private static int findFilterPriority(Dictionary<String, String> initparams) {
		if (initparams == null) {
			return 0;
		}

		String filterPriority = initparams.get(Const.FILTER_PRIORITY);

		if (filterPriority == null) {
			return 0;
		}

		try {
			int result = Integer.parseInt(filterPriority);
			if (result >= -1000 && result <= 1000) {
				return result;
			}
		}
		catch (NumberFormatException e) {
			// fall through
		}

		throw new IllegalArgumentException(
			"filter-priority must be an integer between -1000 and 1000 but " +
				"was: " + filterPriority);
	}

	public void registerHttpServiceResources(
		Bundle bundle, String alias, String name, HttpContext httpContext) throws NamespaceException {
		if (alias == null) {
			throw new IllegalArgumentException("Alias cannot be null");
		}
		if (name == null) {
			throw new IllegalArgumentException("Name cannot be null");
		}
		String pattern = alias;
		if (pattern.startsWith("/*.")) { //$NON-NLS-1$
			pattern = pattern.substring(1);
		}
		else if (!pattern.contains("*.") && //$NON-NLS-1$
				!pattern.endsWith(Const.SLASH_STAR) &&
				!pattern.endsWith(Const.SLASH)) {
			pattern += Const.SLASH_STAR;
		}

		ContextController.checkPattern(alias);

		synchronized (legacyMappings) {
			HttpServiceObjectRegistration objectRegistration = null;
			HttpContextHelperFactory factory = getOrRegisterHttpContextHelperFactory(bundle, httpContext);
			try {
				String fullAlias = getFullAlias(alias, factory);
				HttpServiceObjectRegistration existing = legacyMappings.get(fullAlias);
				if (existing != null) {
					throw new PatternInUseException(alias);
				}
				Dictionary<String, Object> props = new Hashtable<String, Object>();
				props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_TARGET, targetFilter);
				props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN, pattern);
				props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX, name);
				props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, factory.getFilter());
				props.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE);
				props.put(Const.EQUINOX_LEGACY_REGISTRATION_PROP, Boolean.TRUE);
				ServiceRegistration<?> registration = bundle.getBundleContext().registerService(String.class, "resource", props); //$NON-NLS-1$
				objectRegistration = new HttpServiceObjectRegistration(fullAlias, registration, factory, bundle);

				Set<HttpServiceObjectRegistration> objectRegistrations = bundleRegistrations.get(bundle);
				if (objectRegistrations == null) {
					objectRegistrations = new HashSet<HttpServiceObjectRegistration>();
					bundleRegistrations.put(bundle, objectRegistrations);
				}
				objectRegistrations.add(objectRegistration);

				Map<String, String> aliasCustomizations = bundleAliasCustomizations.get(bundle);
				if (aliasCustomizations == null) {
					aliasCustomizations = new HashMap<String, String>();
					bundleAliasCustomizations.put(bundle, aliasCustomizations);
				}
				aliasCustomizations.put(alias, fullAlias);
				legacyMappings.put(objectRegistration.serviceKey, objectRegistration);
			} finally {
				if (objectRegistration == null || !legacyMappings.containsKey(objectRegistration.serviceKey)) {
					// something bad happened above (likely going to throw a runtime exception)
					// need to clean up the factory reference
					decrementFactoryUseCount(factory);
				}
			}
		}
	}

	public void registerHttpServiceServlet(
		Bundle bundle, String alias, Servlet servlet, Dictionary<String, String> initparams, HttpContext httpContext) throws NamespaceException, ServletException{
		if (alias == null) {
			throw new IllegalArgumentException("Alias cannot be null");
		}
		if (servlet == null) {
			throw new IllegalArgumentException("Servlet cannot be null");
		}

		ContextController.checkPattern(alias);

		synchronized (legacyMappings) {
			LegacyServlet legacyServlet = new LegacyServlet(servlet);
			if (getRegisteredObjects().contains(legacyServlet)) {
				throw new ServletAlreadyRegisteredException(servlet);
			}
			HttpServiceObjectRegistration objectRegistration = null;
			ServiceRegistration<Servlet> registration = null;
			HttpContextHelperFactory factory = getOrRegisterHttpContextHelperFactory(bundle, httpContext);
			try {
				String fullAlias = getFullAlias(alias, factory);
				HttpServiceObjectRegistration existing = legacyMappings.get(fullAlias);
				if (existing != null) {
					throw new PatternInUseException(alias);
				}
				String servletName = servlet.getClass().getName();
				if ((initparams != null) && (initparams.get(Const.SERVLET_NAME) != null)) {
					servletName = initparams.get(Const.SERVLET_NAME);
				}

				Dictionary<String, Object> props = new Hashtable<String, Object>();
				props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_TARGET, targetFilter);
				props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, alias);
				props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, servletName);
				props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, factory.getFilter());
				props.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE);
				props.put(Const.EQUINOX_LEGACY_REGISTRATION_PROP, Boolean.TRUE);
				fillInitParams(props, initparams, HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX);

				registration = bundle.getBundleContext().registerService(Servlet.class, legacyServlet, props);

				// check that init got called and did not throw an exception
				legacyServlet.checkForError();

				objectRegistration = new HttpServiceObjectRegistration(fullAlias, registration, factory, bundle);

				Set<HttpServiceObjectRegistration> objectRegistrations = bundleRegistrations.get(bundle);
				if (objectRegistrations == null) {
					objectRegistrations = new HashSet<HttpServiceObjectRegistration>();
					bundleRegistrations.put(bundle, objectRegistrations);
				}
				objectRegistrations.add(objectRegistration);

				Map<String, String> aliasCustomizations = bundleAliasCustomizations.get(bundle);
				if (aliasCustomizations == null) {
					aliasCustomizations = new HashMap<String, String>();
					bundleAliasCustomizations.put(bundle, aliasCustomizations);
				}
				aliasCustomizations.put(alias, fullAlias);

				legacyMappings.put(objectRegistration.serviceKey, objectRegistration);
			} finally {
				if (objectRegistration == null || !legacyMappings.containsKey(objectRegistration.serviceKey)) {
					// something bad happened above (likely going to throw a runtime exception)
					// need to clean up the factory reference
					decrementFactoryUseCount(factory);
					if (registration != null) {
						registration.unregister();
					}
				}
			}
		}
	}

	private String getFullAlias(String alias, HttpContextHelperFactory factory) {
		AtomicReference<ContextController> controllerRef = contextServiceTracker.getService(factory.getServiceReference());
		if (controllerRef != null) {
			ContextController controller = controllerRef.get();
			if (controller != null) {
				return controller.getContextPath() + alias;
			}
		}
		return alias;
	}

	public void unregisterHttpServiceAlias(Bundle bundle, String alias) {
		synchronized (legacyMappings) {
			Map<String, String> aliasCustomizations = bundleAliasCustomizations.get(bundle);
			String aliasCustomization = aliasCustomizations == null ? null : aliasCustomizations.remove(alias);
			if (aliasCustomization == null) {
				throw new IllegalArgumentException("The bundle did not register the alias: " + alias); //$NON-NLS-1$
			}
			HttpServiceObjectRegistration objectRegistration = legacyMappings.get(aliasCustomization);
			if (objectRegistration == null) {
				throw new IllegalArgumentException("No registration found for alias: " + alias); //$NON-NLS-1$
			}
			Set<HttpServiceObjectRegistration> objectRegistrations = bundleRegistrations.get(bundle);
			if (objectRegistrations == null || !objectRegistrations.remove(objectRegistration))
			{
				throw new IllegalArgumentException("The bundle did not register the alias: " + alias); //$NON-NLS-1$
			}

			try {
				objectRegistration.registration.unregister();
			} catch (IllegalStateException e) {
				// ignore; already unregistered
			}
			decrementFactoryUseCount(objectRegistration.factory);
			legacyMappings.remove(aliasCustomization);

		}
	}

	public void unregisterHttpServiceFilter(Bundle bundle, Filter filter) {
		synchronized (legacyMappings) {
			HttpServiceObjectRegistration objectRegistration = legacyMappings.get(filter);
			if (objectRegistration == null) {
				throw new IllegalArgumentException("No registration found for filter: " + filter); //$NON-NLS-1$
			}
			Set<HttpServiceObjectRegistration> objectRegistrations = bundleRegistrations.get(bundle);
			if (objectRegistrations == null || !objectRegistrations.remove(objectRegistration))
			{
				throw new IllegalArgumentException("The bundle did not register the filter: " + filter); //$NON-NLS-1$
			}
			try {
				objectRegistration.registration.unregister();
			} catch (IllegalStateException e) {
				// ignore; already unregistered
			}
			decrementFactoryUseCount(objectRegistration.factory);
			legacyMappings.remove(filter);
		}
	}

	public void unregisterHttpServiceObjects(Bundle bundle) {
		synchronized (legacyMappings) {
			bundleAliasCustomizations.remove(bundle);
			Set<HttpServiceObjectRegistration> objectRegistrations = bundleRegistrations.remove(bundle);
			if (objectRegistrations != null) {
				for (HttpServiceObjectRegistration objectRegistration : objectRegistrations) {
					try {
						objectRegistration.registration.unregister();
					} catch (IllegalStateException e) {
						// ignore; already unregistered
					}
					decrementFactoryUseCount(objectRegistration.factory);
					legacyMappings.remove(objectRegistration.serviceKey);
				}
			}
		}
	}

	private HttpContextHelperFactory getOrRegisterHttpContextHelperFactory(Bundle initiatingBundle, HttpContext httpContext) {
		if (httpContext == null) {
			throw new NullPointerException("A null HttpContext is not allowed."); //$NON-NLS-1$
		}
		synchronized (httpContextHelperFactories) {
			HttpContextHelperFactory factory = httpContextHelperFactories.get(httpContext);
			if (factory == null) {
				factory = new HttpContextHelperFactory(httpContext);
				Dictionary<String, Object> props = new Hashtable<String, Object>();
				props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, httpContext.getClass().getName().replaceAll("[^a-zA-Z_0-9\\-]", "_") + "-" + generateLegacyId()); //$NON-NLS-1$
				props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, "/"); //$NON-NLS-1$
				props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_TARGET, targetFilter);
				props.put(Const.EQUINOX_LEGACY_CONTEXT_HELPER, Boolean.TRUE);
				props.put(Const.EQUINOX_LEGACY_HTTP_CONTEXT_INITIATING_ID, initiatingBundle.getBundleId());
				factory.setRegistration(consumingContext.registerService(ServletContextHelper.class, factory, props));
				httpContextHelperFactories.put(httpContext, factory);
			}
			factory.incrementUseCount();
			return factory;
		}
	}

	private void decrementFactoryUseCount(HttpContextHelperFactory factory) {
		synchronized (httpContextHelperFactories) {
			if (factory.decrementUseCount() == 0) {
				httpContextHelperFactories.remove(factory.getHttpContext());
			}
		}
	}

	private static org.osgi.framework.Filter createResourceFilter(BundleContext context) {
		StringBuilder sb = new StringBuilder();

		sb.append("(&("); //$NON-NLS-1$
		sb.append(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX);
		sb.append("=*)("); //$NON-NLS-1$
		sb.append(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN);
		sb.append("=*))"); //$NON-NLS-1$

		try {
			return context.createFilter(sb.toString());
		}
		catch (InvalidSyntaxException ise) {
			throw new IllegalArgumentException(ise);
		}
	}

	private static org.osgi.framework.Filter createServletFilter(BundleContext context) {
		StringBuilder sb = new StringBuilder();

		sb.append("(&(objectClass="); //$NON-NLS-1$
		sb.append(Servlet.class.getName());
		sb.append(")(|("); //$NON-NLS-1$
		sb.append(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ERROR_PAGE);
		sb.append("=*)("); //$NON-NLS-1$
		sb.append(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN);
		sb.append("=*)))"); //$NON-NLS-1$

		try {
			return context.createFilter(sb.toString());
		}
		catch (InvalidSyntaxException ise) {
			throw new IllegalArgumentException(ise);
		}
	}

	private static org.osgi.framework.Filter createFilterFilter(BundleContext context) {
		StringBuilder sb = new StringBuilder();

		sb.append("(&(objectClass="); //$NON-NLS-1$
		sb.append(Filter.class.getName());
		sb.append(")(|("); //$NON-NLS-1$
		sb.append(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN);
		sb.append("=*)("); //$NON-NLS-1$
		sb.append(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_REGEX);
		sb.append("=*)("); //$NON-NLS-1$
		sb.append(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_SERVLET);
		sb.append("=*)))"); //$NON-NLS-1$

		try {
			return context.createFilter(sb.toString());
		}
		catch (InvalidSyntaxException ise) {
			throw new IllegalArgumentException(ise);
		}
	}

	private static org.osgi.framework.Filter createListenerFilter(BundleContext context) {
		StringBuilder sb = new StringBuilder();

		sb.append("(&"); //$NON-NLS-1$
		sb.append("(").append(HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER).append("~=true)"); //$NON-NLS-1$ //$NON-NLS-2$
		sb.append("(|"); //$NON-NLS-1$
		sb.append("(objectClass=").append(ServletContextListener.class.getName()).append(")"); //$NON-NLS-1$ //$NON-NLS-2$
		sb.append("(objectClass=").append(ServletContextAttributeListener.class.getName()).append(")"); //$NON-NLS-1$ //$NON-NLS-2$
		sb.append("(objectClass=").append(ServletRequestListener.class.getName()).append(")"); //$NON-NLS-1$ //$NON-NLS-2$
		sb.append("(objectClass=").append(ServletRequestAttributeListener.class.getName()).append(")"); //$NON-NLS-1$ //$NON-NLS-2$
		sb.append("(objectClass=").append(HttpSessionListener.class.getName()).append(")"); //$NON-NLS-1$ //$NON-NLS-2$
		sb.append("(objectClass=").append(HttpSessionAttributeListener.class.getName()).append(")"); //$NON-NLS-1$ //$NON-NLS-2$
		sb.append(")"); //$NON-NLS-1$
		sb.append(")"); //$NON-NLS-1$

		try {
			return context.createFilter(sb.toString());
		}
		catch (InvalidSyntaxException ise) {
			throw new IllegalArgumentException(ise);
		}
	}

	public org.osgi.framework.Filter getListenerFilter() {
		return listenerServiceFilter;
	}

	public org.osgi.framework.Filter getFilterFilter() {
		return filterServiceFilter;
	}

	public org.osgi.framework.Filter getServletFilter() {
		return servletServiceFilter;
	}

	public org.osgi.framework.Filter getResourceFilter() {
		return resourceServiceFilter;
	}

	public void recordFailedListenerDTO(
		ServiceReference<EventListener> serviceReference,
		FailedListenerDTO failedListenerDTO) {

		if (failedListenerDTOs.containsKey(serviceReference)) {
			return;
		}

		failedListenerDTOs.put(serviceReference, failedListenerDTO);
	}

	private void recordFailedServletContextDTO(
		ServiceReference<ServletContextHelper> serviceReference, String contextName,
		String contextPath, int failureReason) {

		FailedServletContextDTO failedServletContextDTO = new FailedServletContextDTO();

		failedServletContextDTO.attributes = Collections.emptyMap();
		failedServletContextDTO.contextName = contextName;
		failedServletContextDTO.contextPath = contextPath;
		failedServletContextDTO.errorPageDTOs = new ErrorPageDTO[0];
		failedServletContextDTO.failureReason = failureReason;
		failedServletContextDTO.filterDTOs = new FilterDTO[0];
		failedServletContextDTO.initParams = ServiceProperties.parseInitParams(
			serviceReference, HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_INIT_PARAM_PREFIX);
		failedServletContextDTO.listenerDTOs = new ListenerDTO[0];
		failedServletContextDTO.name = contextName;
		failedServletContextDTO.resourceDTOs = new ResourceDTO[0];
		failedServletContextDTO.serviceId = (Long)serviceReference.getProperty(Constants.SERVICE_ID);
		failedServletContextDTO.servletDTOs = new ServletDTO[0];

		failedServletContextDTOs.put(serviceReference, failedServletContextDTO);
	}

	public void removeFailedListenerDTO(
		ServiceReference<EventListener> serviceReference) {

		failedListenerDTOs.remove(serviceReference);
	}

	private Map<String, Object> attributes;
	private final String targetFilter;
	private final ServiceRegistration<ServletContextHelper> defaultContextReg;
	private ServletContext parentServletContext;

	private BundleContext trackingContext;
	private BundleContext consumingContext;

	private final org.osgi.framework.Filter servletServiceFilter;
	private final org.osgi.framework.Filter resourceServiceFilter;
	private final org.osgi.framework.Filter filterServiceFilter;
	private final org.osgi.framework.Filter listenerServiceFilter;

	// BEGIN of old HttpService support
	private Map<HttpContext, HttpContextHelperFactory> httpContextHelperFactories =
		Collections.synchronizedMap(new HashMap<HttpContext, HttpContextHelperFactory>());
	private Map<Object, HttpServiceObjectRegistration> legacyMappings =
		Collections.synchronizedMap(new HashMap<Object, HttpServiceObjectRegistration>());
	private Map<Bundle, Set<HttpServiceObjectRegistration>> bundleRegistrations =
		new HashMap<Bundle, Set<HttpServiceObjectRegistration>>();
	private Map<Bundle, Map<String, String>> bundleAliasCustomizations = new HashMap<Bundle, Map<String,String>>();
	// END of old HttpService support

	private ConcurrentMap<ServiceReference<ServletContextHelper>, ContextController> controllerMap =
		new ConcurrentHashMap<ServiceReference<ServletContextHelper>, ContextController>();

	private final ConcurrentMap<ServiceReference<EventListener>, FailedListenerDTO> failedListenerDTOs =
		new ConcurrentHashMap<ServiceReference<EventListener>, FailedListenerDTO>();
	private final ConcurrentMap<ServiceReference<ServletContextHelper>, FailedServletContextDTO> failedServletContextDTOs =
		new ConcurrentHashMap<ServiceReference<ServletContextHelper>, FailedServletContextDTO>();

	private AtomicLong legacyIdGenerator = new AtomicLong(0);

	private Set<Object> registeredObjects = Collections.newSetFromMap(new ConcurrentHashMap<Object, Boolean>());

	private ServiceTracker<ServletContextHelper, AtomicReference<ContextController>> contextServiceTracker;
	private ServiceTracker<ContextPathCustomizer, ContextPathCustomizer> contextPathAdaptorTracker;
	private ContextPathCustomizerHolder contextPathCustomizerHolder;

	static class DefaultServletContextHelperFactory implements ServiceFactory<ServletContextHelper> {
		@Override
		public ServletContextHelper getService(
			Bundle bundle,
			ServiceRegistration<ServletContextHelper> registration) {
			return new DefaultServletContextHelper(bundle);
		}

		@Override
		public void ungetService(
			Bundle bundle,
			ServiceRegistration<ServletContextHelper> registration,
			ServletContextHelper service) {
			// do nothing
		}
	}

	static class DefaultServletContextHelper extends ServletContextHelper {
		public DefaultServletContextHelper(Bundle b) {
			super(b);
		}
	}

	static class LegacyServiceObject {
		final AtomicReference<Exception> error = new AtomicReference<Exception>(new ServletException("The init() method was never called.")); //$NON-NLS-1$
		public void checkForError() {
			Exception result = error.get();
			if (result != null) {
				HttpServiceImpl.unchecked(result);
			}
		}
	}

	public static class LegacyFilterFactory extends LegacyServiceObject implements PrototypeServiceFactory<Filter> {
		final Filter filter;

		public LegacyFilterFactory(Filter filter) {
			this.filter = filter;
		}

		@Override
		public Filter getService(Bundle bundle, ServiceRegistration<Filter> registration) {
			return new LegacyFilter();
		}

		@Override
		public void ungetService(
			Bundle bundle, ServiceRegistration<Filter> registration, Filter service) {
			// do nothing
		}

		// NOTE we do not do the same equals check here for filter that we do for servlet
		// this is because we must allow filter to be applied to all context helpers
		// TODO this means it is still possible that init() will get called if the same filter
		// is registered multiple times.  This is unfortunate but is an error case on the client anyway.
		class LegacyFilter implements Filter {
			/**
			 * @throws ServletException
			 */
			@Override
			public void init(FilterConfig filterConfig) throws ServletException {
				try {
					filter.init(filterConfig);
					error.set(null);
				} catch (Exception e){
					error.set(e);
					HttpServiceImpl.unchecked(e);
				}
			}

			@Override
			public void doFilter(
				ServletRequest request, ServletResponse response, FilterChain chain)
				throws IOException, ServletException {
				filter.doFilter(request, response, chain);
			}

			@Override
			public void destroy() {
				filter.destroy();
			}
		}
	}

	static class LegacyServlet extends LegacyServiceObject implements Servlet {
		final Servlet servlet;

		public LegacyServlet(Servlet servlet) {
			this.servlet = servlet;
		}

		/**
		 * @throws ServletException
		 */
		@Override
		public void init(ServletConfig config)
			throws ServletException {
			try {
				servlet.init(config);
				error.set(null);
			} catch (Exception e){
				error.set(e);
				HttpServiceImpl.unchecked(e);
			}
		}

		@Override
		public ServletConfig getServletConfig() {
			return servlet.getServletConfig();
		}

		@Override
		public void
			service(ServletRequest req, ServletResponse res)
				throws ServletException, IOException {
			servlet.service(req, res);
		}

		@Override
		public String getServletInfo() {
			return servlet.getServletInfo();
		}

		@Override
		public void destroy() {
			servlet.destroy();
		}

		@Override
		public int hashCode() {
			return servlet.hashCode();
		}

		@Override
		public boolean equals(Object other) {
			if (other instanceof LegacyServlet) {
				other = ((LegacyServlet) other).servlet;
			}
			return servlet.equals(other);
		}
	}

	static class ContextPathCustomizerHolder implements ServiceTrackerCustomizer<ContextPathCustomizer, ContextPathCustomizer> {
		private final BundleContext context;
		private final ServiceTracker<ServletContextHelper, AtomicReference<ContextController>> contextServiceTracker;
		private final NavigableMap<ServiceReference<ContextPathCustomizer>, ContextPathCustomizer> pathCustomizers =
			new TreeMap<ServiceReference<ContextPathCustomizer>, ContextPathCustomizer>(Collections.reverseOrder());

		public ContextPathCustomizerHolder(
			BundleContext context,
			ServiceTracker<ServletContextHelper, AtomicReference<ContextController>> contextServiceTracker) {
			super();
			this.context = context;
			this.contextServiceTracker = contextServiceTracker;
		}

		@Override
		public ContextPathCustomizer addingService(
			ServiceReference<ContextPathCustomizer> reference) {
			ContextPathCustomizer service = context.getService(reference);
			boolean reset = false;
			synchronized (pathCustomizers) {
				pathCustomizers.put(reference, service);
				reset = pathCustomizers.firstKey().equals(reference);
			}
			if (reset) {
				contextServiceTracker.close();
				contextServiceTracker.open();
			}
			return service;
		}

		@Override
		public void modifiedService(
			ServiceReference<ContextPathCustomizer> reference,
			ContextPathCustomizer service) {
			removedService(reference, service);
			addingService(reference);
		}
		@Override
		public void removedService(
			ServiceReference<ContextPathCustomizer> reference,
			ContextPathCustomizer service) {
			boolean reset = false;
			synchronized (pathCustomizers) {
				ServiceReference<ContextPathCustomizer> currentFirst = pathCustomizers.firstKey();
				pathCustomizers.remove(reference);
				reset = currentFirst.equals(reference);
			}

			// only reset if the tracker is still open
			if (reset && contextServiceTracker.getTrackingCount() >= 0) {

				contextServiceTracker.close();
				contextServiceTracker.open();
			}
			context.ungetService(reference);
		}

		ContextPathCustomizer getHighestRanked() {
			synchronized (pathCustomizers) {
				Map.Entry<ServiceReference<ContextPathCustomizer>, ContextPathCustomizer> firstEntry = pathCustomizers.firstEntry();
				return firstEntry == null ? null : firstEntry.getValue();
			}
		}
	}

}
