FELIX-4100 : Support osgi.http.whiteboard.target whiteboard property
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1659544 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java b/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java
index c286cf0..48d88da 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java
@@ -33,9 +33,11 @@
import org.apache.felix.http.base.internal.service.HttpServiceRuntimeImpl;
import org.apache.felix.http.base.internal.whiteboard.WhiteboardHttpService;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.runtime.HttpServiceRuntime;
+import org.osgi.service.http.runtime.HttpServiceRuntimeConstants;
public final class HttpServiceController
{
@@ -59,10 +61,12 @@
*/
private static final String FELIX_HTTP_SHARED_SERVLET_CONTEXT_ATTRIBUTES = "org.apache.felix.http.shared_servlet_context_attributes";
+ /** Compat property for previous versions. */
+ private static final String OBSOLETE_REG_PROPERTY_ENDPOINTS = "osgi.http.service.endpoints";
+
private final BundleContext bundleContext;
private final HandlerRegistry registry;
private final Dispatcher dispatcher;
- private final Hashtable<String, Object> serviceProps;
private final ServletContextAttributeListenerManager contextAttributeListener;
private final ServletRequestListenerManager requestListener;
private final ServletRequestAttributeListenerManager requestAttributeListener;
@@ -71,15 +75,18 @@
private final boolean sharedContextAttributes;
private final HttpServicePlugin plugin;
private volatile WhiteboardHttpService whiteboardHttpService;
- private volatile ServiceRegistration serviceReg;
- private volatile ServiceRegistration<HttpServiceRuntime> runtimeReg;
+
+ private final Hashtable<String, Object> httpServiceProps = new Hashtable<String, Object>();;
+ private volatile ServiceRegistration httpServiceReg;
+
+ private volatile ServiceRegistration<HttpServiceRuntime> runtimeServiceReg;
+ private final Hashtable<String, Object> runtimeServiceProps = new Hashtable<String, Object>();;
public HttpServiceController(BundleContext bundleContext)
{
this.bundleContext = bundleContext;
this.registry = new HandlerRegistry();
this.dispatcher = new Dispatcher(this.registry);
- this.serviceProps = new Hashtable<String, Object>();
this.contextAttributeListener = new ServletContextAttributeListenerManager(bundleContext);
this.requestListener = new ServletRequestListenerManager(bundleContext);
this.requestAttributeListener = new ServletRequestAttributeListenerManager(bundleContext);
@@ -121,12 +128,26 @@
public void setProperties(Hashtable<String, Object> props)
{
- this.serviceProps.clear();
- this.serviceProps.putAll(props);
+ this.httpServiceProps.clear();
+ this.httpServiceProps.putAll(props);
- if (this.serviceReg != null)
+ if ( this.httpServiceProps.get(HttpServiceRuntimeConstants.HTTP_SERVICE_ENDPOINT_ATTRIBUTE) != null )
{
- this.serviceReg.setProperties(this.serviceProps);
+ this.httpServiceProps.put(OBSOLETE_REG_PROPERTY_ENDPOINTS,
+ this.httpServiceProps.get(HttpServiceRuntimeConstants.HTTP_SERVICE_ENDPOINT_ATTRIBUTE));
+ }
+
+ // runtime service gets the same props for now
+ this.runtimeServiceProps.clear();
+ this.runtimeServiceProps.putAll(this.httpServiceProps);
+
+ if (this.httpServiceReg != null)
+ {
+ this.httpServiceReg.setProperties(this.httpServiceProps);
+
+ this.runtimeServiceProps.put(HttpServiceRuntimeConstants.HTTP_SERVICE_ID_ATTRIBUTE,
+ this.httpServiceReg.getReference().getProperty(Constants.SERVICE_ID));
+ this.runtimeServiceReg.setProperties(this.runtimeServiceProps);
}
}
@@ -142,10 +163,18 @@
String[] ifaces = new String[] { HttpService.class.getName(), ExtHttpService.class.getName() };
HttpServiceFactory factory = new HttpServiceFactory(servletContext, this.registry, this.contextAttributeListener, this.sharedContextAttributes);
- this.serviceReg = this.bundleContext.registerService(ifaces, factory, this.serviceProps);
- this.whiteboardHttpService = new WhiteboardHttpService(this.bundleContext, servletContext, this.registry);
+ this.httpServiceReg = this.bundleContext.registerService(ifaces, factory, this.httpServiceProps);
- this.runtimeReg = this.bundleContext.registerService(HttpServiceRuntime.class, new HttpServiceRuntimeImpl(), null);
+ this.runtimeServiceProps.put(HttpServiceRuntimeConstants.HTTP_SERVICE_ID_ATTRIBUTE,
+ this.httpServiceReg.getReference().getProperty(Constants.SERVICE_ID));
+ this.runtimeServiceReg = this.bundleContext.registerService(HttpServiceRuntime.class,
+ new HttpServiceRuntimeImpl(),
+ this.runtimeServiceProps);
+
+ this.whiteboardHttpService = new WhiteboardHttpService(this.bundleContext,
+ servletContext,
+ this.registry,
+ this.runtimeServiceReg.getReference());
}
public void unregister()
@@ -156,10 +185,10 @@
this.whiteboardHttpService = null;
}
- if ( this.runtimeReg != null )
+ if ( this.runtimeServiceReg != null )
{
- this.runtimeReg.unregister();
- this.runtimeReg = null;
+ this.runtimeServiceReg.unregister();
+ this.runtimeServiceReg = null;
}
this.sessionAttributeListener.close();
@@ -170,16 +199,16 @@
this.plugin.unregister();
- if ( this.serviceReg != null )
+ if ( this.httpServiceReg != null )
{
try
{
- this.serviceReg.unregister();
+ this.httpServiceReg.unregister();
this.registry.shutdown();
}
finally
{
- this.serviceReg = null;
+ this.httpServiceReg = null;
}
}
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/AbstractInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/AbstractInfo.java
index c7ed3ba..0036241 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/AbstractInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/AbstractInfo.java
@@ -24,6 +24,7 @@
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
/**
* Base class for all info objects.
@@ -40,6 +41,9 @@
/** Service reference. */
private final ServiceReference<T> serviceReference;
+ /** Target. */
+ private final String target;
+
public AbstractInfo(final ServiceReference<T> ref)
{
this.serviceId = (Long)ref.getProperty(Constants.SERVICE_ID);
@@ -53,6 +57,7 @@
this.ranking = 0;
}
this.serviceReference = ref;
+ this.target = getStringProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_TARGET);
}
public AbstractInfo(final int ranking, final long serviceId)
@@ -60,6 +65,7 @@
this.ranking = ranking;
this.serviceId = serviceId;
this.serviceReference = null;
+ this.target = null;
}
public boolean isValid()
@@ -221,4 +227,9 @@
return false;
return true;
}
+
+ public String getTarget()
+ {
+ return this.target;
+ }
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletContextHelperManager.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletContextHelperManager.java
index ef35c0f..6e623a3 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletContextHelperManager.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletContextHelperManager.java
@@ -29,6 +29,7 @@
import javax.servlet.ServletContext;
import org.apache.felix.http.base.internal.logger.SystemLogger;
+import org.apache.felix.http.base.internal.runtime.AbstractInfo;
import org.apache.felix.http.base.internal.runtime.FilterInfo;
import org.apache.felix.http.base.internal.runtime.ResourceInfo;
import org.apache.felix.http.base.internal.runtime.ServletContextAttributeListenerInfo;
@@ -40,9 +41,13 @@
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.http.context.ServletContextHelper;
+import org.osgi.service.http.runtime.HttpServiceRuntime;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
public final class ServletContextHelperManager
@@ -61,15 +66,21 @@
private final Bundle bundle;
+ private final ServiceReference<HttpServiceRuntime> runtimeRef;
+
/**
* Create a new servlet context helper manager
* and the default context
*/
- public ServletContextHelperManager(final BundleContext bundleContext, final ServletContext webContext, final WhiteboardHttpService httpService)
+ public ServletContextHelperManager(final BundleContext bundleContext,
+ final ServletContext webContext,
+ final ServiceReference<HttpServiceRuntime> runtimeRef,
+ final WhiteboardHttpService httpService)
{
this.httpService = httpService;
this.webContext = webContext;
this.bundle = bundleContext.getBundle();
+ this.runtimeRef = runtimeRef;
final Dictionary<String, Object> props = new Hashtable<String, Object>();
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, HttpWhiteboardConstants.HTTP_WHITEBOARD_DEFAULT_CONTEXT_NAME);
@@ -188,36 +199,40 @@
*/
public void addContextHelper(final ServletContextHelperInfo info)
{
- if ( info.isValid() )
+ // no failure DTO and no logging if not matching
+ if ( isMatchingService(info) )
{
- final ContextHandler handler = new ContextHandler(info, this.webContext, this.bundle);
- synchronized ( this.contextMap )
+ if ( info.isValid() )
{
- List<ContextHandler> handlerList = this.contextMap.get(info.getName());
- if ( handlerList == null )
+ final ContextHandler handler = new ContextHandler(info, this.webContext, this.bundle);
+ synchronized ( this.contextMap )
{
- handlerList = new ArrayList<ContextHandler>();
- this.contextMap.put(info.getName(), handlerList);
- }
- handlerList.add(handler);
- Collections.sort(handlerList);
- // check for activate/deactivate
- if ( handlerList.get(0) == handler )
- {
- // check for deactivate
- if ( handlerList.size() > 1 )
+ List<ContextHandler> handlerList = this.contextMap.get(info.getName());
+ if ( handlerList == null )
{
- this.deactivate(handlerList.get(1));
+ handlerList = new ArrayList<ContextHandler>();
+ this.contextMap.put(info.getName(), handlerList);
}
- this.activate(handler);
+ handlerList.add(handler);
+ Collections.sort(handlerList);
+ // check for activate/deactivate
+ if ( handlerList.get(0) == handler )
+ {
+ // check for deactivate
+ if ( handlerList.size() > 1 )
+ {
+ this.deactivate(handlerList.get(1));
+ }
+ this.activate(handler);
+ }
}
}
- }
- else
- {
- // TODO - failure DTO
- final String type = info.getClass().getSimpleName().substring(0, info.getClass().getSimpleName().length() - 4);
- SystemLogger.debug("Ignoring " + type + " service " + info.getServiceReference());
+ else
+ {
+ // TODO - failure DTO
+ final String type = info.getClass().getSimpleName().substring(0, info.getClass().getSimpleName().length() - 4);
+ SystemLogger.debug("Ignoring " + type + " service " + info.getServiceReference());
+ }
}
}
@@ -226,37 +241,41 @@
*/
public void removeContextHelper(final ServletContextHelperInfo info)
{
- synchronized ( this.contextMap )
+ // no failure DTO and no logging if not matching
+ if ( isMatchingService(info) && info.isValid() )
{
- final List<ContextHandler> handlerList = this.contextMap.get(info.getName());
- if ( handlerList != null )
+ synchronized ( this.contextMap )
{
- final Iterator<ContextHandler> i = handlerList.iterator();
- boolean first = true;
- boolean activateNext = false;
- while ( i.hasNext() )
+ final List<ContextHandler> handlerList = this.contextMap.get(info.getName());
+ if ( handlerList != null )
{
- final ContextHandler handler = i.next();
- if ( handler.getContextInfo().compareTo(info) == 0 )
+ final Iterator<ContextHandler> i = handlerList.iterator();
+ boolean first = true;
+ boolean activateNext = false;
+ while ( i.hasNext() )
{
- i.remove();
- // check for deactivate
- if ( first )
+ final ContextHandler handler = i.next();
+ if ( handler.getContextInfo().compareTo(info) == 0 )
{
- this.deactivate(handler);
- activateNext = true;
+ i.remove();
+ // check for deactivate
+ if ( first )
+ {
+ this.deactivate(handler);
+ activateNext = true;
+ }
+ break;
}
- break;
+ first = false;
}
- first = false;
- }
- if ( handlerList.isEmpty() )
- {
- this.contextMap.remove(info.getName());
- }
- else if ( activateNext )
- {
- this.activate(handlerList.get(0));
+ if ( handlerList.isEmpty() )
+ {
+ this.contextMap.remove(info.getName());
+ }
+ else if ( activateNext )
+ {
+ this.activate(handlerList.get(0));
+ }
}
}
}
@@ -284,23 +303,27 @@
*/
public void addWhiteboardService(@Nonnull final WhiteboardServiceInfo<?> info)
{
- if ( info.isValid() )
+ // no logging and no DTO if other target service
+ if ( isMatchingService(info) )
{
- synchronized ( this.contextMap )
+ if ( info.isValid() )
{
- final List<ContextHandler> handlerList = this.getMatchingContexts(info);
- this.servicesMap.put(info, handlerList);
- for(final ContextHandler h : handlerList)
+ synchronized ( this.contextMap )
{
- this.registerWhiteboardService(h, info);
+ final List<ContextHandler> handlerList = this.getMatchingContexts(info);
+ this.servicesMap.put(info, handlerList);
+ for(final ContextHandler h : handlerList)
+ {
+ this.registerWhiteboardService(h, info);
+ }
}
}
- }
- else
- {
- // TODO - failure DTO
- final String type = info.getClass().getSimpleName().substring(0, info.getClass().getSimpleName().length() - 4);
- SystemLogger.debug("Ignoring " + type + " service " + info.getServiceReference());
+ else
+ {
+ // TODO - failure DTO
+ final String type = info.getClass().getSimpleName().substring(0, info.getClass().getSimpleName().length() - 4);
+ SystemLogger.debug("Ignoring " + type + " service " + info.getServiceReference());
+ }
}
}
@@ -310,14 +333,18 @@
*/
public void removeWhiteboardService(@Nonnull final WhiteboardServiceInfo<?> info)
{
- synchronized ( this.contextMap )
+ // no logging and no DTO if other target service
+ if ( isMatchingService(info) && info.isValid() )
{
- final List<ContextHandler> handlerList = this.servicesMap.remove(info);
- if ( handlerList != null )
+ synchronized ( this.contextMap )
{
- for(final ContextHandler h : handlerList)
+ final List<ContextHandler> handlerList = this.servicesMap.remove(info);
+ if ( handlerList != null )
{
- this.unregisterWhiteboardService(h, info);
+ for(final ContextHandler h : handlerList)
+ {
+ this.unregisterWhiteboardService(h, info);
+ }
}
}
}
@@ -372,4 +399,28 @@
handler.removeListener((ServletContextAttributeListenerInfo)info );
}
}
+
+ /**
+ * Check whether the service is specifying a target http service runtime
+ * and if so if that is matching this runtime
+ */
+ private boolean isMatchingService(final AbstractInfo<?> info)
+ {
+ final String target = info.getTarget();
+ if ( target != null )
+ {
+ try
+ {
+ final Filter f = this.bundle.getBundleContext().createFilter(target);
+ return f.match(this.runtimeRef);
+ }
+ catch ( final InvalidSyntaxException ise)
+ {
+ // log and ignore service
+ SystemLogger.error("Invalid target filter expression for " + info.getServiceReference() + " : " + target, ise);
+ return false;
+ }
+ }
+ return true;
+ }
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardHttpService.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardHttpService.java
index 50fd8ee..e5f194c 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardHttpService.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardHttpService.java
@@ -40,6 +40,8 @@
import org.apache.felix.http.base.internal.whiteboard.tracker.ServletTracker;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceObjects;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.runtime.HttpServiceRuntime;
import org.osgi.util.tracker.ServiceTracker;
public final class WhiteboardHttpService
@@ -61,11 +63,12 @@
*/
public WhiteboardHttpService(final BundleContext bundleContext,
final ServletContext context,
- final HandlerRegistry handlerRegistry)
+ final HandlerRegistry handlerRegistry,
+ final ServiceReference<HttpServiceRuntime> runtimeRef)
{
this.handlerRegistry = handlerRegistry;
this.bundleContext = bundleContext;
- this.contextManager = new ServletContextHelperManager(bundleContext, context, this);
+ this.contextManager = new ServletContextHelperManager(bundleContext, context, runtimeRef, this);
addTracker(new FilterTracker(bundleContext, contextManager));
addTracker(new ServletTracker(bundleContext, this.contextManager));
addTracker(new ResourceTracker(bundleContext, this.contextManager));
diff --git a/http/bridge/src/main/java/org/apache/felix/http/bridge/internal/BridgeActivator.java b/http/bridge/src/main/java/org/apache/felix/http/bridge/internal/BridgeActivator.java
index 9ef8b11..8e338b9 100644
--- a/http/bridge/src/main/java/org/apache/felix/http/bridge/internal/BridgeActivator.java
+++ b/http/bridge/src/main/java/org/apache/felix/http/bridge/internal/BridgeActivator.java
@@ -26,12 +26,10 @@
import org.apache.felix.http.base.internal.AbstractHttpActivator;
import org.apache.felix.http.base.internal.logger.SystemLogger;
import org.osgi.framework.Constants;
+import org.osgi.service.http.runtime.HttpServiceRuntimeConstants;
public final class BridgeActivator extends AbstractHttpActivator
{
- /** Endpoint service registration property from RFC 189 */
- private static final String REG_PROPERTY_ENDPOINTS = "osgi.http.service.endpoints";
-
/** Framework property containing the endpoint registration information (optional). */
private static final String FELIX_HTTP_SERVICE_ENDPOINTS = "org.apache.felix.http.service.endpoints";
@@ -60,7 +58,8 @@
if ( getBundleContext().getProperty(FELIX_HTTP_SERVICE_ENDPOINTS) != null )
{
final Hashtable<String, Object> serviceRegProps = new Hashtable<String, Object>();
- serviceRegProps.put(REG_PROPERTY_ENDPOINTS, getBundleContext().getProperty(FELIX_HTTP_SERVICE_ENDPOINTS));
+ serviceRegProps.put(HttpServiceRuntimeConstants.HTTP_SERVICE_ENDPOINT_ATTRIBUTE,
+ getBundleContext().getProperty(FELIX_HTTP_SERVICE_ENDPOINTS));
this.getHttpServiceController().setProperties(serviceRegProps);
}
diff --git a/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/JettyService.java b/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/JettyService.java
index 2910881..81a9055 100644
--- a/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/JettyService.java
+++ b/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/JettyService.java
@@ -70,6 +70,7 @@
import org.osgi.service.cm.ManagedService;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
+import org.osgi.service.http.runtime.HttpServiceRuntimeConstants;
import org.osgi.util.tracker.BundleTracker;
import org.osgi.util.tracker.BundleTrackerCustomizer;
import org.osgi.util.tracker.ServiceTracker;
@@ -80,9 +81,6 @@
/** PID for configuration of the HTTP service. */
private static final String PID = "org.apache.felix.http";
- /** Endpoint service registration property from RFC 189 */
- private static final String REG_PROPERTY_ENDPOINTS = "osgi.http.service.endpoints";
-
private static final String HEADER_WEB_CONTEXT_PATH = "Web-ContextPath";
private static final String HEADER_ACTIVATION_POLICY = "Bundle-ActivationPolicy";
private static final String WEB_SYMBOLIC_NAME = "osgi.web.symbolicname";
@@ -598,7 +596,8 @@
}
}
}
- props.put(REG_PROPERTY_ENDPOINTS, endpoints.toArray(new String[endpoints.size()]));
+ props.put(HttpServiceRuntimeConstants.HTTP_SERVICE_ENDPOINT_ATTRIBUTE,
+ endpoints.toArray(new String[endpoints.size()]));
}
private Deployment startWebAppBundle(Bundle bundle, String contextPath)
diff --git a/http/jetty/src/test/java/org/apache/felix/http/jetty/internal/JettyServiceTest.java b/http/jetty/src/test/java/org/apache/felix/http/jetty/internal/JettyServiceTest.java
index 3dd546b..b1f2c41 100644
--- a/http/jetty/src/test/java/org/apache/felix/http/jetty/internal/JettyServiceTest.java
+++ b/http/jetty/src/test/java/org/apache/felix/http/jetty/internal/JettyServiceTest.java
@@ -51,10 +51,13 @@
import org.mockito.Matchers;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.Version;
import org.osgi.service.http.context.ServletContextHelper;
+import org.osgi.service.http.runtime.HttpServiceRuntime;
public class JettyServiceTest extends TestCase
{
@@ -89,10 +92,19 @@
when(mockBundle.getSymbolicName()).thenReturn("main");
when(mockBundle.getVersion()).thenReturn(new Version("1.0.0"));
when(mockBundle.getHeaders()).thenReturn(new Hashtable<String, String>());
+ final ServiceReference ref = mock(ServiceReference.class);
+ when(ref.getProperty(Constants.SERVICE_ID)).thenReturn(1L);
final ServiceRegistration reg = mock(ServiceRegistration.class);
+ when(reg.getReference()).thenReturn(ref);
when(mockBundleContext.registerService((Class<ServletContextHelper>)Matchers.isNotNull(),
(ServiceFactory<ServletContextHelper>)Matchers.any(ServiceFactory.class),
Matchers.any(Dictionary.class))).thenReturn(reg);
+ when(mockBundleContext.registerService(Matchers.<String[]>any(),
+ Matchers.any(ServiceFactory.class),
+ Matchers.any(Dictionary.class))).thenReturn(reg);
+ when(mockBundleContext.registerService((Class<HttpServiceRuntime>)Matchers.isNotNull(),
+ Matchers.any(HttpServiceRuntime.class),
+ Matchers.any(Dictionary.class))).thenReturn(reg);
httpServiceController = new HttpServiceController(mockBundleContext);
dispatcherServlet = new DispatcherServlet(httpServiceController);