blob: e4ecd05861a9a3207d02029c5472dd491c406f65 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2015 Cognos Incorporated, IBM Corporation 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:
* Cognos Incorporated - initial API and implementation
* IBM Corporation - bug fixes and enhancements
* Raymond Augé <raymond.auge@liferay.com> - Bug 436698
*******************************************************************************/
package org.eclipse.equinox.http.servlet.internal;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.servlet.*;
import javax.servlet.http.HttpServlet;
import org.eclipse.equinox.http.servlet.ExtendedHttpService;
import org.eclipse.equinox.http.servlet.internal.servlet.ProxyServlet;
import org.eclipse.equinox.http.servlet.internal.util.HttpTuple;
import org.eclipse.equinox.http.servlet.internal.util.UMDictionaryMap;
import org.osgi.framework.*;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.runtime.HttpServiceRuntime;
import org.osgi.service.http.runtime.HttpServiceRuntimeConstants;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
public class Activator
implements BundleActivator, ServiceTrackerCustomizer<HttpServlet, HttpTuple> {
private static final String DEFAULT_SERVICE_DESCRIPTION = "Equinox Servlet Bridge"; //$NON-NLS-1$
private static final String DEFAULT_SERVICE_VENDOR = "Eclipse.org"; //$NON-NLS-1$
private static final String PROP_GLOBAL_WHITEBOARD = "equinox.http.global.whiteboard"; //$NON-NLS-1$
public static final String UNIQUE_SERVICE_ID = "equinox.http.id"; //$NON-NLS-1$
private static final String[] HTTP_SERVICES_CLASSES = new String[] {
HttpService.class.getName(), ExtendedHttpService.class.getName()
};
private static volatile BundleContext context;
private static ConcurrentMap<ProxyServlet, Object> registrations =
new ConcurrentHashMap<ProxyServlet, Object>();
private ServiceTracker<HttpServlet, HttpTuple> serviceTracker;
public static void addProxyServlet(ProxyServlet proxyServlet) {
Object previousRegistration = registrations.putIfAbsent(
proxyServlet, proxyServlet);
if (!(previousRegistration instanceof ServiceRegistration) &&
(context != null)) {
ServiceRegistration<HttpServlet> serviceRegistration =
context.registerService(
HttpServlet.class, proxyServlet,
new Hashtable<String, Object>());
registrations.put(proxyServlet, serviceRegistration);
}
}
public static void unregisterHttpService(ProxyServlet proxyServlet) {
Object registration = registrations.remove(proxyServlet);
if (registration instanceof ServiceRegistration) {
ServiceRegistration<?> serviceRegistration =
(ServiceRegistration<?>)registration;
serviceRegistration.unregister();
}
}
public void start(BundleContext bundleContext) throws Exception {
context = bundleContext;
processRegistrations();
serviceTracker = new ServiceTracker<HttpServlet, HttpTuple>(
context, HttpServlet.class, this);
serviceTracker.open();
}
public void stop(BundleContext bundleContext) throws Exception {
serviceTracker.close();
serviceTracker = null;
context = null;
}
public HttpTuple addingService(
ServiceReference<HttpServlet> serviceReference) {
HttpServlet httpServlet = context.getService(serviceReference);
if (!(httpServlet instanceof ProxyServlet)) {
context.ungetService(serviceReference);
return null;
}
ProxyServlet proxyServlet = (ProxyServlet)httpServlet;
ServletConfig servletConfig = proxyServlet.getServletConfig();
ServletContext servletContext = servletConfig.getServletContext();
String[] httpServiceEndpoints = getHttpServiceEndpoints(
servletContext, servletConfig.getServletName());
Dictionary<String, Object> serviceProperties =
new Hashtable<String, Object>(3);
Enumeration<String> initparameterNames =
servletConfig.getInitParameterNames();
while (initparameterNames.hasMoreElements()) {
String name = initparameterNames.nextElement();
serviceProperties.put(
name, servletConfig.getInitParameter(name));
}
if (serviceProperties.get(Constants.SERVICE_VENDOR) == null) {
serviceProperties.put(
Constants.SERVICE_VENDOR, DEFAULT_SERVICE_VENDOR);
}
if (serviceProperties.get(Constants.SERVICE_DESCRIPTION) == null) {
serviceProperties.put(
Constants.SERVICE_DESCRIPTION, DEFAULT_SERVICE_DESCRIPTION);
}
if (serviceProperties.get(
HttpServiceRuntimeConstants.HTTP_SERVICE_ENDPOINT) == null) {
serviceProperties.put(
HttpServiceRuntimeConstants.HTTP_SERVICE_ENDPOINT,
httpServiceEndpoints);
}
// need a unique id for our service to match old HttpService HttpContext
serviceProperties.put(UNIQUE_SERVICE_ID, new Random().nextLong());
// white board support
// determine if the system bundle context should be used:
boolean useSystemContext = Boolean.valueOf(context.getProperty(PROP_GLOBAL_WHITEBOARD));
BundleContext trackingContext = useSystemContext ? context.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).getBundleContext() : context;
HttpServiceRuntimeImpl httpServiceRuntime = new HttpServiceRuntimeImpl(
trackingContext, context, servletContext,
new UMDictionaryMap<String, Object>(serviceProperties));
proxyServlet.setHttpServiceRuntimeImpl(httpServiceRuntime);
// imperative API support;
// the http service must be registered first so we can get its service id
HttpServiceFactory httpServiceFactory = new HttpServiceFactory(
httpServiceRuntime);
ServiceRegistration<?> hsfRegistration = context.registerService(
HTTP_SERVICES_CLASSES, httpServiceFactory, serviceProperties);
serviceProperties.put(HttpServiceRuntimeConstants.HTTP_SERVICE_ID, Collections.singletonList(hsfRegistration.getReference().getProperty(Constants.SERVICE_ID)));
ServiceRegistration<HttpServiceRuntime> hsrRegistration =
context.registerService(
HttpServiceRuntime.class, httpServiceRuntime,
serviceProperties);
return new HttpTuple(
proxyServlet, httpServiceFactory, hsfRegistration,
httpServiceRuntime, hsrRegistration);
}
public void modifiedService(
ServiceReference<HttpServlet> serviceReference, HttpTuple httpTuple) {
removedService(serviceReference, httpTuple);
addingService(serviceReference);
}
public void removedService(
ServiceReference<HttpServlet> serviceReference, HttpTuple httpTuple) {
context.ungetService(serviceReference);
httpTuple.destroy();
}
private String[] getHttpServiceEndpoints(
ServletContext servletContext, String servletName) {
int majorVersion = servletContext.getMajorVersion();
if (majorVersion < 3) {
servletContext.log(
"The http container does not support servlet 3.0+. " +
"Therefore, the value of " +
HttpServiceRuntimeConstants.HTTP_SERVICE_ENDPOINT +
" cannot be calculated.");
return new String[0];
}
String contextPath = servletContext.getContextPath();
ServletRegistration servletRegistration = null;
try {
servletRegistration = servletContext.getServletRegistration(servletName);
} catch (UnsupportedOperationException e) {
servletContext.log("Could not find the servlet registration for the servlet: " + servletName, e); //$NON-NLS-1$
}
if (servletRegistration == null) {
return new String[0];
}
Collection<String> mappings = servletRegistration.getMappings();
List<String> httpServiceEndpoints = new ArrayList<String>();
for (String mapping : mappings) {
if (mapping.indexOf('/') == 0) {
if (mapping.charAt(mapping.length() - 1) == '*') {
mapping = mapping.substring(0, mapping.length() - 2);
if ((mapping.length() > 1) &&
(mapping.charAt(mapping.length() - 1) != '/')) {
mapping += '/';
}
}
httpServiceEndpoints.add(contextPath + mapping);
}
}
return httpServiceEndpoints.toArray(
new String[httpServiceEndpoints.size()]);
}
private void processRegistrations() {
Iterator<Entry<ProxyServlet, Object>> iterator =
registrations.entrySet().iterator();
while (iterator.hasNext()) {
Entry<ProxyServlet, Object> entry = iterator.next();
ProxyServlet proxyServlet = entry.getKey();
Object value = entry.getValue();
if (!(value instanceof ServiceRegistration)) {
ServiceRegistration<HttpServlet> serviceRegistration =
context.registerService(
HttpServlet.class, proxyServlet,
new Hashtable<String, Object>());
entry.setValue(serviceRegistration);
}
}
}
}