FELIX-4904 : Provide a way to associate whiteboard services with the default context of the http service
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1681788 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 6b74a77..d0aa361 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
@@ -18,6 +18,7 @@
import java.util.Hashtable;
+import javax.annotation.Nonnull;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionEvent;
@@ -106,12 +107,12 @@
this.whiteboardManager.setProperties(props);
}
- public void register(final ServletContext servletContext)
+ public void register(@Nonnull final ServletContext containerContext)
{
this.registry.init();
- this.httpServiceFactory.start(servletContext);
- this.whiteboardManager.start(servletContext);
+ this.httpServiceFactory.start(containerContext);
+ this.whiteboardManager.start(containerContext);
this.dispatcher.setWhiteboardManager(this.whiteboardManager);
}
@@ -120,15 +121,8 @@
{
this.dispatcher.setWhiteboardManager(null);
- if ( this.whiteboardManager != null )
- {
- this.whiteboardManager.stop();
- }
-
- if ( this.httpServiceFactory != null )
- {
- this.httpServiceFactory.stop();
- }
+ this.httpServiceFactory.stop();
+ this.whiteboardManager.stop();
this.registry.shutdown();
this.httpSessionListener = null;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ContextHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ContextHandler.java
new file mode 100644
index 0000000..0dcfe5c
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ContextHandler.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.handler;
+
+import javax.annotation.Nonnull;
+
+import org.apache.felix.http.base.internal.registry.PerContextHandlerRegistry;
+import org.apache.felix.http.base.internal.runtime.FilterInfo;
+import org.apache.felix.http.base.internal.runtime.ListenerInfo;
+import org.apache.felix.http.base.internal.runtime.ServletContextHelperInfo;
+import org.apache.felix.http.base.internal.runtime.ServletInfo;
+import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
+
+public interface ContextHandler
+{
+
+ ServletContextHelperInfo getContextInfo();
+
+ /**
+ * Create a servlet handler
+ * @param servletInfo The servlet info
+ * @return {@code null} if the servlet context could not be created, a handler otherwise
+ */
+ ServletHandler getServletContextAndCreateServletHandler(@Nonnull final ServletInfo servletInfo);
+
+ /**
+ * Create a filter handler
+ * @param info The filter info
+ * @return {@code null} if the servlet context could not be created, a handler otherwise
+ */
+ FilterHandler getServletContextAndCreateFilterHandler(@Nonnull final FilterInfo info);
+
+ /**
+ * Create a listener handler
+ * @param info The listener info
+ * @return {@code null} if the servlet context could not be created, a handler otherwise
+ */
+ ListenerHandler getServletContextAndCreateListenerHandler(@Nonnull final ListenerInfo info);
+
+ void ungetServletContext(@Nonnull final WhiteboardServiceInfo<?> info);
+
+ PerContextHandlerRegistry getRegistry();
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java
index cf9d624..037cf8e 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java
@@ -20,14 +20,10 @@
import javax.annotation.Nonnull;
import javax.servlet.DispatcherType;
-import org.apache.felix.http.base.internal.context.ExtServletContext;
+import org.apache.felix.http.base.internal.handler.ContextHandler;
import org.apache.felix.http.base.internal.handler.FilterHandler;
-import org.apache.felix.http.base.internal.handler.HttpServiceServletHandler;
import org.apache.felix.http.base.internal.handler.ListenerHandler;
import org.apache.felix.http.base.internal.handler.ServletHandler;
-import org.apache.felix.http.base.internal.handler.WhiteboardFilterHandler;
-import org.apache.felix.http.base.internal.handler.WhiteboardListenerHandler;
-import org.apache.felix.http.base.internal.handler.WhiteboardServletHandler;
import org.apache.felix.http.base.internal.runtime.FilterInfo;
import org.apache.felix.http.base.internal.runtime.ListenerInfo;
import org.apache.felix.http.base.internal.runtime.ResourceInfo;
@@ -35,8 +31,6 @@
import org.apache.felix.http.base.internal.runtime.ServletInfo;
import org.apache.felix.http.base.internal.runtime.dto.FailedDTOHolder;
import org.apache.felix.http.base.internal.service.HttpServiceFactory;
-import org.apache.felix.http.base.internal.service.ResourceServlet;
-import org.apache.felix.http.base.internal.whiteboard.ContextHandler;
import org.osgi.service.http.runtime.dto.DTOConstants;
import org.osgi.service.http.runtime.dto.ServletContextDTO;
@@ -163,15 +157,11 @@
public int registerServlet(@Nonnull final ContextHandler contextHandler,
@Nonnull final ServletInfo servletInfo)
{
- final ExtServletContext context = contextHandler.getServletContext(servletInfo.getServiceReference().getBundle());
- if ( context == null )
+ final ServletHandler handler = contextHandler.getServletContextAndCreateServletHandler(servletInfo);
+ if ( handler == null )
{
return DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
}
- final ServletHandler handler = new WhiteboardServletHandler(
- contextHandler.getContextInfo().getServiceId(),
- context,
- servletInfo, contextHandler.getBundleContext());
this.servletRegistry.addServlet(handler);
this.errorPageRegistry.addServlet(handler);
return -1;
@@ -186,7 +176,7 @@
{
this.servletRegistry.removeServlet(servletInfo, true);
this.errorPageRegistry.removeServlet(servletInfo, true);
- contextHandler.ungetServletContext(servletInfo.getServiceReference().getBundle());
+ contextHandler.ungetServletContext(servletInfo);
}
/**
@@ -197,15 +187,11 @@
public int registerFilter(@Nonnull final ContextHandler contextHandler,
@Nonnull final FilterInfo filterInfo)
{
- final ExtServletContext context = contextHandler.getServletContext(filterInfo.getServiceReference().getBundle());
- if ( context == null )
+ final FilterHandler handler = contextHandler.getServletContextAndCreateFilterHandler(filterInfo);
+ if ( handler == null )
{
return DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
}
- final FilterHandler handler = new WhiteboardFilterHandler(
- contextHandler.getContextInfo().getServiceId(),
- context,
- filterInfo, contextHandler.getBundleContext());
this.filterRegistry.addFilter(handler);
return -1;
}
@@ -218,7 +204,7 @@
public void unregisterFilter(@Nonnull final ContextHandler contextHandler, @Nonnull final FilterInfo filterInfo)
{
this.filterRegistry.removeFilter(filterInfo, true);
- contextHandler.ungetServletContext(filterInfo.getServiceReference().getBundle());
+ contextHandler.ungetServletContext(filterInfo);
}
/**
@@ -231,16 +217,11 @@
public int registerListeners(@Nonnull final ContextHandler contextHandler,
@Nonnull final ListenerInfo info)
{
- final ExtServletContext context = contextHandler.getServletContext(info.getServiceReference().getBundle());
- if ( context == null )
+ final ListenerHandler handler = contextHandler.getServletContextAndCreateListenerHandler(info);
+ if ( handler == null )
{
return DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
}
- final ListenerHandler handler = new WhiteboardListenerHandler(
- contextHandler.getContextInfo().getServiceId(),
- context,
- info,
- contextHandler.getBundleContext());
this.eventListenerRegistry.addListeners(handler);
return -1;
}
@@ -254,7 +235,7 @@
public void unregisterListeners(@Nonnull final ContextHandler contextHandler, @Nonnull final ListenerInfo info)
{
this.eventListenerRegistry.removeListeners(info);
- contextHandler.ungetServletContext(info.getServiceReference().getBundle());
+ contextHandler.ungetServletContext(info);
}
/**
@@ -267,17 +248,11 @@
{
final ServletInfo servletInfo = new ServletInfo(resourceInfo);
- final ExtServletContext context = contextHandler.getServletContext(servletInfo.getServiceReference().getBundle());
- if ( context == null )
+ final ServletHandler handler = contextHandler.getServletContextAndCreateServletHandler(servletInfo);
+ if ( handler == null )
{
return DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE;
}
-
- final ServletHandler handler = new HttpServiceServletHandler(
- contextHandler.getContextInfo().getServiceId(),
- context,
- servletInfo, new ResourceServlet(resourceInfo.getPrefix()));
-
this.servletRegistry.addServlet(handler);
return -1;
}
@@ -289,19 +264,31 @@
*/
public void unregisterResource(@Nonnull final ContextHandler contextHandler, @Nonnull final ResourceInfo resourceInfo)
{
- final ServletInfo servletInfo = new ServletInfo(resourceInfo);
- this.servletRegistry.removeServlet(servletInfo, true);
- contextHandler.ungetServletContext(servletInfo.getServiceReference().getBundle());
+ this.servletRegistry.removeServlet(new ServletInfo(resourceInfo), true);
+ contextHandler.ungetServletContext(resourceInfo);
}
- public FilterHandler[] getFilterHandlers(@CheckForNull final ServletHandler servletHandler,
+ /**
+ * Get filter handlers for the request uri
+ * @param servletHandler The servlet handler (might be null)
+ * @param dispatcherType The dispatcher type
+ * @param requestURI The request uri
+ * @return The array of filter handlers, the array might be empty.
+ */
+ public @Nonnull FilterHandler[] getFilterHandlers(@CheckForNull final ServletHandler servletHandler,
@Nonnull final DispatcherType dispatcherType,
@Nonnull final String requestURI)
{
return this.filterRegistry.getFilterHandlers(servletHandler, dispatcherType, requestURI);
}
- public ServletHandler getErrorHandler(int code, Throwable exception)
+ /**
+ * Get the servlet handling the error.
+ * @param code The error code
+ * @param exception The optional exception
+ * @return The servlet handler or {@code null}.
+ */
+ public @CheckForNull ServletHandler getErrorHandler(final int code, @CheckForNull final Throwable exception)
{
return this.errorPageRegistry.get(exception, code);
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletInfo.java
index d78fedb..682ad36 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletInfo.java
@@ -114,10 +114,9 @@
*/
public ServletInfo(final String name,
final String pattern,
- final int serviceRanking,
final Map<String, String> initParams)
{
- super(serviceRanking);
+ super(Integer.MAX_VALUE);
this.name = name;
this.patterns = new String[] {pattern};
this.initParams = Collections.unmodifiableMap(initParams);
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java b/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java
index 5551159..47fbd94 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java
@@ -40,7 +40,7 @@
public final class HttpServiceFactory
implements ServiceFactory<HttpService>
{
- public static final String HTTP_SERVICE_CONTEXT_NAME = "Http Service context";
+ public static final String HTTP_SERVICE_CONTEXT_NAME = "org.osgi.service.http";
public static final long HTTP_SERVICE_CONTEXT_SERVICE_ID = -1;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/PerBundleHttpServiceImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/service/PerBundleHttpServiceImpl.java
index 266b65c..5870c09 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/PerBundleHttpServiceImpl.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/service/PerBundleHttpServiceImpl.java
@@ -202,7 +202,7 @@
this.localServlets.add(servlet);
}
- final ServletInfo servletInfo = new ServletInfo(String.format("%s_%d", servlet.getClass(), this.hashCode()), alias, 0, paramMap);
+ final ServletInfo servletInfo = new ServletInfo(String.format("%s_%d", servlet.getClass(), this.hashCode()), alias, paramMap);
final ExtServletContext httpContext = getServletContext(context);
boolean success = false;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ContextHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ContextHandler.java
deleted file mode 100644
index 604bc2c..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ContextHandler.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.felix.http.base.internal.whiteboard;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nonnull;
-import javax.servlet.ServletContext;
-
-import org.apache.felix.http.base.internal.context.ExtServletContext;
-import org.apache.felix.http.base.internal.registry.HandlerRegistry;
-import org.apache.felix.http.base.internal.registry.PerContextHandlerRegistry;
-import org.apache.felix.http.base.internal.runtime.ServletContextHelperInfo;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceObjects;
-import org.osgi.service.http.context.ServletContextHelper;
-
-public final class ContextHandler implements Comparable<ContextHandler>
-{
- /** The info object for the context. */
- private final ServletContextHelperInfo info;
-
- private final ServletContext webContext;
-
- /** The shared part of the servlet context. */
- private volatile ServletContext sharedContext;
-
- /** The http bundle. */
- private final Bundle bundle;
-
- /** A map of all created servlet contexts. Each bundle gets it's own instance. */
- private final Map<Long, ContextHolder> perBundleContextMap = new HashMap<Long, ContextHolder>();
-
- private volatile PerContextHandlerRegistry registry;
-
- public ContextHandler(final ServletContextHelperInfo info,
- final ServletContext webContext,
- final Bundle bundle)
- {
- this.webContext = webContext;
- this.info = info;
- this.bundle = bundle;
- }
-
- public BundleContext getBundleContext()
- {
- return this.bundle.getBundleContext();
- }
-
- public ServletContextHelperInfo getContextInfo()
- {
- return this.info;
- }
-
- @Override
- public int compareTo(final ContextHandler o)
- {
- return this.info.compareTo(o.info);
- }
-
- /**
- * Activate this context.
- * @return {@code true} if it succeeded.
- */
- public boolean activate(final HandlerRegistry registry)
- {
- this.registry = new PerContextHandlerRegistry(this.info);
- this.sharedContext = new SharedServletContextImpl(webContext,
- info.getName(),
- info.getPath(),
- info.getInitParameters(),
- this.registry.getEventListenerRegistry());
- final boolean activate = getServletContext(bundle) != null;
- if ( !activate )
- {
- this.registry = null;
- this.sharedContext = null;
- }
- else
- {
- registry.add(this.registry);
- }
- return activate;
- }
-
- /**
- * Deactivate this context.
- */
- public void deactivate(final HandlerRegistry registry)
- {
- registry.remove(this.info);
- this.registry = null;
- this.sharedContext = null;
- this.ungetServletContext(bundle);
- // TODO we should clear all state
- }
-
- public ServletContext getSharedContext()
- {
- return sharedContext;
- }
-
- public ExtServletContext getServletContext(@CheckForNull final Bundle bundle)
- {
- if ( bundle == null )
- {
- return null;
- }
- final Long key = bundle.getBundleId();
- synchronized ( this.perBundleContextMap )
- {
- ContextHolder holder = this.perBundleContextMap.get(key);
- if ( holder == null )
- {
- final BundleContext ctx = bundle.getBundleContext();
- final ServiceObjects<ServletContextHelper> so = (ctx == null ? null : ctx.getServiceObjects(this.info.getServiceReference()));
- if ( so != null )
- {
- final ServletContextHelper service = so.getService();
- if ( service != null )
- {
- holder = new ContextHolder();
- holder.servletContextHelper = service;
- holder.servletContext = new PerBundleServletContextImpl(bundle,
- this.sharedContext,
- service,
- this.registry.getEventListenerRegistry());
- this.perBundleContextMap.put(key, holder);
- }
- }
- }
- if ( holder != null )
- {
- holder.counter++;
-
- return holder.servletContext;
- }
- }
- return null;
- }
-
- public void ungetServletContext(@Nonnull final Bundle bundle)
- {
- final Long key = bundle.getBundleId();
- synchronized ( this.perBundleContextMap )
- {
- ContextHolder holder = this.perBundleContextMap.get(key);
- if ( holder != null )
- {
- holder.counter--;
- if ( holder.counter == 0 )
- {
- this.perBundleContextMap.remove(key);
- if ( holder.servletContextHelper != null )
- {
- final BundleContext ctx = bundle.getBundleContext();
- final ServiceObjects<ServletContextHelper> so = (ctx == null ? null : ctx.getServiceObjects(this.info.getServiceReference()));
- if ( so != null )
- {
- so.ungetService(holder.servletContextHelper);
- }
- }
- }
- }
- }
- }
-
- private static final class ContextHolder
- {
- public long counter;
- public ExtServletContext servletContext;
- public ServletContextHelper servletContextHelper;
- }
-
- public PerContextHandlerRegistry getRegistry()
- {
- return this.registry;
- }
-}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardContextHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardContextHandler.java
new file mode 100644
index 0000000..d98fecf
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardContextHandler.java
@@ -0,0 +1,292 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.whiteboard;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import javax.servlet.ServletContext;
+
+import org.apache.felix.http.base.internal.context.ExtServletContext;
+import org.apache.felix.http.base.internal.handler.ContextHandler;
+import org.apache.felix.http.base.internal.handler.FilterHandler;
+import org.apache.felix.http.base.internal.handler.HttpServiceServletHandler;
+import org.apache.felix.http.base.internal.handler.ListenerHandler;
+import org.apache.felix.http.base.internal.handler.ServletHandler;
+import org.apache.felix.http.base.internal.handler.WhiteboardFilterHandler;
+import org.apache.felix.http.base.internal.handler.WhiteboardListenerHandler;
+import org.apache.felix.http.base.internal.handler.WhiteboardServletHandler;
+import org.apache.felix.http.base.internal.registry.HandlerRegistry;
+import org.apache.felix.http.base.internal.registry.PerContextHandlerRegistry;
+import org.apache.felix.http.base.internal.runtime.FilterInfo;
+import org.apache.felix.http.base.internal.runtime.ListenerInfo;
+import org.apache.felix.http.base.internal.runtime.ServletContextHelperInfo;
+import org.apache.felix.http.base.internal.runtime.ServletInfo;
+import org.apache.felix.http.base.internal.runtime.WhiteboardServiceInfo;
+import org.apache.felix.http.base.internal.service.ResourceServlet;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceObjects;
+import org.osgi.service.http.context.ServletContextHelper;
+
+public final class WhiteboardContextHandler implements ContextHandler, Comparable<ContextHandler>
+{
+ /** The info object for the context. */
+ private final ServletContextHelperInfo info;
+
+ private final ServletContext webContext;
+
+ /** The http bundle. */
+ private final Bundle httpBundle;
+
+ /** A map of all created servlet contexts. Each bundle gets it's own instance. */
+ private final Map<Long, ContextHolder> perBundleContextMap = new HashMap<Long, ContextHolder>();
+
+ private volatile PerContextHandlerRegistry registry;
+
+ /** The shared part of the servlet context. */
+ private volatile ServletContext sharedContext;
+
+ public WhiteboardContextHandler(final ServletContextHelperInfo info,
+ final ServletContext webContext,
+ final Bundle httpBundle)
+ {
+ this.webContext = webContext;
+ this.info = info;
+ this.httpBundle = httpBundle;
+ }
+
+ public BundleContext getBundleContext()
+ {
+ return this.httpBundle.getBundleContext();
+ }
+
+ @Override
+ public ServletContextHelperInfo getContextInfo()
+ {
+ return this.info;
+ }
+
+ @Override
+ public int compareTo(final ContextHandler o)
+ {
+ return this.info.compareTo(o.getContextInfo());
+ }
+
+ /**
+ * Activate this context.
+ * @return {@code true} if it succeeded.
+ */
+ public boolean activate(final HandlerRegistry registry)
+ {
+ this.registry = new PerContextHandlerRegistry(this.info);
+ this.sharedContext = new SharedServletContextImpl(webContext,
+ info.getName(),
+ info.getPath(),
+ info.getInitParameters(),
+ this.registry.getEventListenerRegistry());
+ final boolean activate = getServletContext(httpBundle) != null;
+ if ( !activate )
+ {
+ this.registry = null;
+ this.sharedContext = null;
+ }
+ else
+ {
+ registry.add(this.registry);
+ }
+ return activate;
+ }
+
+ /**
+ * Deactivate this context.
+ */
+ public void deactivate(final HandlerRegistry registry)
+ {
+ registry.remove(this.info);
+ this.registry = null;
+ this.sharedContext = null;
+ this.ungetServletContext(httpBundle);
+ this.perBundleContextMap.clear();
+ }
+
+ public ServletContext getSharedContext()
+ {
+ return sharedContext;
+ }
+
+ public ExtServletContext getServletContext(@CheckForNull final Bundle bundle)
+ {
+ if ( bundle == null )
+ {
+ return null;
+ }
+ final Long key = bundle.getBundleId();
+ synchronized ( this.perBundleContextMap )
+ {
+ ContextHolder holder = this.perBundleContextMap.get(key);
+ if ( holder == null )
+ {
+ final BundleContext ctx = bundle.getBundleContext();
+ final ServiceObjects<ServletContextHelper> so = (ctx == null ? null : ctx.getServiceObjects(this.info.getServiceReference()));
+ if ( so != null )
+ {
+ final ServletContextHelper service = so.getService();
+ if ( service != null )
+ {
+ holder = new ContextHolder();
+ holder.servletContextHelper = service;
+ holder.servletContext = new PerBundleServletContextImpl(bundle,
+ this.sharedContext,
+ service,
+ this.registry.getEventListenerRegistry());
+ this.perBundleContextMap.put(key, holder);
+ }
+ }
+ }
+ if ( holder != null )
+ {
+ holder.counter++;
+
+ return holder.servletContext;
+ }
+ }
+ return null;
+ }
+
+ public void ungetServletContext(@Nonnull final Bundle bundle)
+ {
+ final Long key = bundle.getBundleId();
+ synchronized ( this.perBundleContextMap )
+ {
+ ContextHolder holder = this.perBundleContextMap.get(key);
+ if ( holder != null )
+ {
+ holder.counter--;
+ if ( holder.counter == 0 )
+ {
+ this.perBundleContextMap.remove(key);
+ if ( holder.servletContextHelper != null )
+ {
+ final BundleContext ctx = bundle.getBundleContext();
+ final ServiceObjects<ServletContextHelper> so = (ctx == null ? null : ctx.getServiceObjects(this.info.getServiceReference()));
+ if ( so != null )
+ {
+ so.ungetService(holder.servletContextHelper);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Create a servlet handler
+ * @param servletInfo The servlet info
+ * @return {@code null} if the servlet context could not be created, a handler otherwise
+ */
+ @Override
+ public ServletHandler getServletContextAndCreateServletHandler(@Nonnull final ServletInfo servletInfo)
+ {
+ final ExtServletContext servletContext = this.getServletContext(servletInfo.getServiceReference().getBundle());
+ if ( servletContext == null )
+ {
+ return null;
+ }
+ final ServletHandler handler;
+ if ( servletInfo.isResource() )
+ {
+ handler = new HttpServiceServletHandler(
+ this.info.getServiceId(),
+ servletContext,
+ servletInfo,
+ new ResourceServlet(servletInfo.getPrefix()));
+ }
+ else
+ {
+ handler = new WhiteboardServletHandler(
+ this.info.getServiceId(),
+ servletContext,
+ servletInfo,
+ this.httpBundle.getBundleContext());
+ }
+ return handler;
+ }
+
+ /**
+ * Create a filter handler
+ * @param info The filter info
+ * @return {@code null} if the servlet context could not be created, a handler otherwise
+ */
+ @Override
+ public FilterHandler getServletContextAndCreateFilterHandler(@Nonnull final FilterInfo info)
+ {
+ final ExtServletContext servletContext = this.getServletContext(info.getServiceReference().getBundle());
+ if ( servletContext == null )
+ {
+ return null;
+ }
+ final FilterHandler handler = new WhiteboardFilterHandler(
+ this.info.getServiceId(),
+ servletContext,
+ info,
+ this.httpBundle.getBundleContext());
+ return handler;
+ }
+
+ /**
+ * Create a listener handler
+ * @param info The listener info
+ * @return {@code null} if the servlet context could not be created, a handler otherwise
+ */
+ @Override
+ public ListenerHandler getServletContextAndCreateListenerHandler(@Nonnull final ListenerInfo info)
+ {
+ final ExtServletContext servletContext = this.getServletContext(info.getServiceReference().getBundle());
+ if ( servletContext == null )
+ {
+ return null;
+ }
+ final ListenerHandler handler = new WhiteboardListenerHandler(
+ this.info.getServiceId(),
+ servletContext,
+ info,
+ this.httpBundle.getBundleContext());
+ return handler;
+ }
+
+ @Override
+ public void ungetServletContext(@Nonnull final WhiteboardServiceInfo<?> info)
+ {
+ this.ungetServletContext(info.getServiceReference().getBundle());
+ }
+
+ private static final class ContextHolder
+ {
+ public long counter;
+ public ExtServletContext servletContext;
+ public ServletContextHelper servletContextHelper;
+ }
+
+ @Override
+ public PerContextHandlerRegistry getRegistry()
+ {
+ return this.registry;
+ }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java
index 844fb5d..ecabd93 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java
@@ -41,6 +41,7 @@
import org.apache.felix.http.base.internal.console.HttpServicePlugin;
import org.apache.felix.http.base.internal.context.ExtServletContext;
+import org.apache.felix.http.base.internal.handler.ContextHandler;
import org.apache.felix.http.base.internal.handler.HttpSessionWrapper;
import org.apache.felix.http.base.internal.handler.ListenerHandler;
import org.apache.felix.http.base.internal.logger.SystemLogger;
@@ -81,17 +82,17 @@
public final class WhiteboardManager
{
- private final BundleContext bundleContext;
+ private final BundleContext httpBundleContext;
private final HttpServiceFactory httpServiceFactory;
private final HttpServiceRuntimeImpl serviceRuntime;
/** A map containing all servlet context registrations. Mapped by context name */
- private final Map<String, List<ContextHandler>> contextMap = new HashMap<String, List<ContextHandler>>();
+ private final Map<String, List<WhiteboardContextHandler>> contextMap = new HashMap<String, List<WhiteboardContextHandler>>();
/** A map with all servlet/filter registrations, mapped by abstract info. */
- private final Map<WhiteboardServiceInfo<?>, List<ContextHandler>> servicesMap = new HashMap<WhiteboardServiceInfo<?>, List<ContextHandler>>();
+ private final Map<WhiteboardServiceInfo<?>, List<WhiteboardContextHandler>> servicesMap = new HashMap<WhiteboardServiceInfo<?>, List<WhiteboardContextHandler>>();
private final HandlerRegistry registry;
@@ -117,30 +118,30 @@
final HttpServiceFactory httpServiceFactory,
final HandlerRegistry registry)
{
- this.bundleContext = bundleContext;
+ this.httpBundleContext = bundleContext;
this.httpServiceFactory = httpServiceFactory;
this.registry = registry;
this.serviceRuntime = new HttpServiceRuntimeImpl(registry, this);
this.plugin = new HttpServicePlugin(bundleContext, this.serviceRuntime);
}
- public void start(final ServletContext context)
+ public void start(final ServletContext containerContext)
{
this.serviceRuntime.setAttribute(HttpServiceRuntimeConstants.HTTP_SERVICE_ID,
Collections.singletonList(this.httpServiceFactory.getHttpServiceServiceId()));
- this.runtimeServiceReg = this.bundleContext.registerService(HttpServiceRuntime.class,
+ this.runtimeServiceReg = this.httpBundleContext.registerService(HttpServiceRuntime.class,
serviceRuntime,
this.serviceRuntime.getAttributes());
this.serviceRuntime.setServiceReference(this.runtimeServiceReg.getReference());
- this.webContext = context;
+ this.webContext = containerContext;
final Dictionary<String, Object> props = new Hashtable<String, Object>();
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, HttpWhiteboardConstants.HTTP_WHITEBOARD_DEFAULT_CONTEXT_NAME);
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, "/");
props.put(Constants.SERVICE_RANKING, Integer.MIN_VALUE);
- this.defaultContextRegistration = bundleContext.registerService(
+ this.defaultContextRegistration = httpBundleContext.registerService(
ServletContextHelper.class,
new ServiceFactory<ServletContextHelper>()
{
@@ -170,11 +171,11 @@
// nothing to do
}
}, props);
- addTracker(new FilterTracker(this.bundleContext, this));
- addTracker(new ListenersTracker(this.bundleContext, this));
- addTracker(new ResourceTracker(this.bundleContext, this));
- addTracker(new ServletContextHelperTracker(this.bundleContext, this));
- addTracker(new ServletTracker(this.bundleContext, this));
+ addTracker(new FilterTracker(this.httpBundleContext, this));
+ addTracker(new ListenersTracker(this.httpBundleContext, this));
+ addTracker(new ResourceTracker(this.httpBundleContext, this));
+ addTracker(new ServletContextHelperTracker(this.httpBundleContext, this));
+ addTracker(new ServletTracker(this.httpBundleContext, this));
this.plugin.register();
}
@@ -230,12 +231,12 @@
{
for(final Long contextId : contextIds)
{
- final ContextHandler handler = this.getContextHandler(contextId);
+ final WhiteboardContextHandler handler = this.getContextHandler(contextId);
if ( handler != null )
{
- final ExtServletContext context = handler.getServletContext(this.bundleContext.getBundle());
+ final ExtServletContext context = handler.getServletContext(this.httpBundleContext.getBundle());
new HttpSessionWrapper(contextId, session, context, true).invalidate();
- handler.ungetServletContext(this.bundleContext.getBundle());
+ handler.ungetServletContext(this.httpBundleContext.getBundle());
}
}
}
@@ -250,7 +251,7 @@
{
for(final Long contextId : contextIds)
{
- final ContextHandler handler = this.getContextHandler(contextId);
+ final WhiteboardContextHandler handler = this.getContextHandler(contextId);
if ( handler != null )
{
handler.getRegistry().getEventListenerRegistry().sessionIdChanged(event, oldSessionId);
@@ -264,7 +265,7 @@
* @param handler The context handler
* @return {@code true} if activation succeeded.
*/
- private boolean activate(final ContextHandler handler)
+ private boolean activate(final WhiteboardContextHandler handler)
{
if ( !handler.activate(this.registry) )
{
@@ -272,7 +273,7 @@
}
final List<WhiteboardServiceInfo<?>> services = new ArrayList<WhiteboardServiceInfo<?>>();
- for(final Map.Entry<WhiteboardServiceInfo<?>, List<ContextHandler>> entry : this.servicesMap.entrySet())
+ for(final Map.Entry<WhiteboardServiceInfo<?>, List<WhiteboardContextHandler>> entry : this.servicesMap.entrySet())
{
if ( entry.getKey().getContextSelectionFilter().match(handler.getContextInfo().getServiceReference()) )
{
@@ -310,14 +311,14 @@
*
* @param handler A context handler
*/
- private void deactivate(final ContextHandler handler)
+ private void deactivate(final WhiteboardContextHandler handler)
{
// services except context listeners first
final List<WhiteboardServiceInfo<?>> listeners = new ArrayList<WhiteboardServiceInfo<?>>();
- final Iterator<Map.Entry<WhiteboardServiceInfo<?>, List<ContextHandler>>> i = this.servicesMap.entrySet().iterator();
+ final Iterator<Map.Entry<WhiteboardServiceInfo<?>, List<WhiteboardContextHandler>>> i = this.servicesMap.entrySet().iterator();
while ( i.hasNext() )
{
- final Map.Entry<WhiteboardServiceInfo<?>, List<ContextHandler>> entry = i.next();
+ final Map.Entry<WhiteboardServiceInfo<?>, List<WhiteboardContextHandler>> entry = i.next();
if ( entry.getValue().remove(handler) )
{
if ( !this.failureStateHandler.remove(entry.getKey(), handler.getContextInfo().getServiceId()) )
@@ -364,15 +365,15 @@
{
synchronized ( this.contextMap )
{
- final ContextHandler handler = new ContextHandler(info,
+ final WhiteboardContextHandler handler = new WhiteboardContextHandler(info,
this.webContext,
- this.bundleContext.getBundle());
+ this.httpBundleContext.getBundle());
// check for activate/deactivate
- List<ContextHandler> handlerList = this.contextMap.get(info.getName());
+ List<WhiteboardContextHandler> handlerList = this.contextMap.get(info.getName());
if ( handlerList == null )
{
- handlerList = new ArrayList<ContextHandler>();
+ handlerList = new ArrayList<WhiteboardContextHandler>();
}
final boolean activate = handlerList.isEmpty() || handlerList.get(0).compareTo(handler) > 0;
if ( activate )
@@ -387,7 +388,7 @@
// check for deactivate
if ( handlerList.size() > 1 )
{
- ContextHandler oldHead = handlerList.get(1);
+ final WhiteboardContextHandler oldHead = handlerList.get(1);
this.deactivate(oldHead);
final String type = info.getClass().getSimpleName().substring(0, info.getClass().getSimpleName().length() - 4);
@@ -436,15 +437,15 @@
{
synchronized ( this.contextMap )
{
- final List<ContextHandler> handlerList = this.contextMap.get(info.getName());
+ final List<WhiteboardContextHandler> handlerList = this.contextMap.get(info.getName());
if ( handlerList != null )
{
- final Iterator<ContextHandler> i = handlerList.iterator();
+ final Iterator<WhiteboardContextHandler> i = handlerList.iterator();
boolean first = true;
boolean activateNext = false;
while ( i.hasNext() )
{
- final ContextHandler handler = i.next();
+ final WhiteboardContextHandler handler = i.next();
if ( handler.getContextInfo().equals(info) )
{
i.remove();
@@ -468,7 +469,7 @@
boolean done = false;
while ( !handlerList.isEmpty() && !done)
{
- final ContextHandler newHead = handlerList.get(0);
+ final WhiteboardContextHandler newHead = handlerList.get(0);
this.failureStateHandler.removeAll(newHead.getContextInfo());
if ( this.activate(newHead) )
@@ -494,12 +495,12 @@
/**
* Find the list of matching contexts for the whiteboard service
*/
- private List<ContextHandler> getMatchingContexts(final WhiteboardServiceInfo<?> info)
+ private List<WhiteboardContextHandler> getMatchingContexts(final WhiteboardServiceInfo<?> info)
{
- final List<ContextHandler> result = new ArrayList<ContextHandler>();
- for(final List<ContextHandler> handlerList : this.contextMap.values())
+ final List<WhiteboardContextHandler> result = new ArrayList<WhiteboardContextHandler>();
+ for(final List<WhiteboardContextHandler> handlerList : this.contextMap.values())
{
- final ContextHandler h = handlerList.get(0);
+ final WhiteboardContextHandler h = handlerList.get(0);
// check whether the servlet context helper is visible to the whiteboard bundle
// see chapter 140.2
boolean visible = h.getContextInfo().getServiceId() < 0; // internal ones are always visible
@@ -542,7 +543,7 @@
{
synchronized ( this.contextMap )
{
- final List<ContextHandler> handlerList = this.getMatchingContexts(info);
+ final List<WhiteboardContextHandler> handlerList = this.getMatchingContexts(info);
this.servicesMap.put(info, handlerList);
if (handlerList.isEmpty())
{
@@ -593,10 +594,10 @@
{
if ( !failureStateHandler.remove(info) )
{
- final List<ContextHandler> handlerList = this.servicesMap.remove(info);
+ final List<WhiteboardContextHandler> handlerList = this.servicesMap.remove(info);
if ( handlerList != null )
{
- for(final ContextHandler h : handlerList)
+ for(final WhiteboardContextHandler h : handlerList)
{
if ( !failureStateHandler.remove(info, h.getContextInfo().getServiceId()) )
{
@@ -672,7 +673,7 @@
* @param handler Context handler
* @param info Whiteboard service info
*/
- private void unregisterWhiteboardService(final ContextHandler handler, final WhiteboardServiceInfo<?> info)
+ private void unregisterWhiteboardService(final WhiteboardContextHandler handler, final WhiteboardServiceInfo<?> info)
{
try
{
@@ -712,7 +713,7 @@
{
try
{
- final Filter f = this.bundleContext.createFilter(target);
+ final Filter f = this.httpBundleContext.createFilter(target);
return f.match(this.runtimeServiceReg.getReference());
}
catch ( final InvalidSyntaxException ise)
@@ -725,13 +726,13 @@
return true;
}
- private ContextHandler getContextHandler(final Long contextId)
+ private WhiteboardContextHandler getContextHandler(final Long contextId)
{
synchronized ( this.contextMap )
{
- for(final List<ContextHandler> handlerList : this.contextMap.values())
+ for(final List<WhiteboardContextHandler> handlerList : this.contextMap.values())
{
- final ContextHandler h = handlerList.get(0);
+ final WhiteboardContextHandler h = handlerList.get(0);
if ( h.getContextInfo().getServiceId() == contextId )
{
return h;
@@ -757,10 +758,10 @@
}
// get sort list of context handlers
- final List<ContextHandler> contextHandlerList = new ArrayList<ContextHandler>();
+ final List<WhiteboardContextHandler> contextHandlerList = new ArrayList<WhiteboardContextHandler>();
synchronized ( this.contextMap )
{
- for (final List<ContextHandler> list : this.contextMap.values())
+ for (final List<WhiteboardContextHandler> list : this.contextMap.values())
{
if ( !list.isEmpty() )
{
@@ -771,7 +772,7 @@
}
Collections.sort(contextHandlerList);
- for (final ContextHandler handler : contextHandlerList)
+ for (final WhiteboardContextHandler handler : contextHandlerList)
{
final ServletContextDTO scDTO = ServletContextDTOBuilder.build(handler.getContextInfo(), handler.getSharedContext(), -1);
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/handler/HttpServiceServletHandlerTest.java b/http/base/src/test/java/org/apache/felix/http/base/internal/handler/HttpServiceServletHandlerTest.java
index afe7b87..9400377 100644
--- a/http/base/src/test/java/org/apache/felix/http/base/internal/handler/HttpServiceServletHandlerTest.java
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/handler/HttpServiceServletHandlerTest.java
@@ -220,7 +220,7 @@
{
map = Collections.emptyMap();
}
- final ServletInfo info = new ServletInfo(null, alias, 0, map);
+ final ServletInfo info = new ServletInfo(null, alias, map);
return new HttpServiceServletHandler(this.context, info, this.servlet);
}
}
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/registry/HandlerRegistryTest.java b/http/base/src/test/java/org/apache/felix/http/base/internal/registry/HandlerRegistryTest.java
index ba24f25..3dbe4c1 100644
--- a/http/base/src/test/java/org/apache/felix/http/base/internal/registry/HandlerRegistryTest.java
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/registry/HandlerRegistryTest.java
@@ -67,7 +67,7 @@
dto.servletDTOs = new ServletDTO[0];
Servlet servlet = Mockito.mock(Servlet.class);
- final ServletInfo info = new ServletInfo("foo", "/foo", 0, Collections.<String, String> emptyMap());
+ final ServletInfo info = new ServletInfo("foo", "/foo", Collections.<String, String> emptyMap());
ServletHandler handler = new HttpServiceServletHandler(null, info, servlet);
assertTrue(registry.getRuntimeInfo(dto, holder));
@@ -79,13 +79,13 @@
assertEquals(1, dto.servletDTOs.length);
assertEquals(info.getServiceId(), dto.servletDTOs[0].serviceId);
- final ServletInfo info2 = new ServletInfo("bar", "/bar", 0, Collections.<String, String> emptyMap());
+ final ServletInfo info2 = new ServletInfo("bar", "/bar", Collections.<String, String> emptyMap());
ServletHandler handler2 = new HttpServiceServletHandler(null, info2, Mockito.mock(Servlet.class));
registry.getRegistry(handler.getContextServiceId()).registerServlet(handler2);
assertTrue(registry.getRuntimeInfo(dto, holder));
assertEquals(2, dto.servletDTOs.length);
- final ServletInfo info3 = new ServletInfo("zar", "/foo", 0, Collections.<String, String> emptyMap());
+ final ServletInfo info3 = new ServletInfo("zar", "/foo", Collections.<String, String> emptyMap());
ServletHandler handler3 = new HttpServiceServletHandler(null,info3, Mockito.mock(Servlet.class));
registry.getRegistry(handler.getContextServiceId()).registerServlet(handler3);
assertTrue(registry.getRuntimeInfo(dto, holder));
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/whiteboard/FailureStateHandlerTest.java b/http/base/src/test/java/org/apache/felix/http/base/internal/whiteboard/FailureStateHandlerTest.java
index 09eaa06..3597f6d 100644
--- a/http/base/src/test/java/org/apache/felix/http/base/internal/whiteboard/FailureStateHandlerTest.java
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/whiteboard/FailureStateHandlerTest.java
@@ -48,7 +48,7 @@
@Test public void testAddRemoveNoContext()
{
- final ServletInfo info = new ServletInfo("test", "/test", 3, Collections.<String, String> emptyMap());
+ final ServletInfo info = new ServletInfo("test", "/test", Collections.<String, String> emptyMap());
final FailureStateHandler handler = new FailureStateHandler();
handler.add(info, DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE);
@@ -69,8 +69,8 @@
@Test public void testAddRemoveContext()
{
- final ServletInfo info1 = new ServletInfo("test", "/test", 3, Collections.<String, String> emptyMap());
- final ServletInfo info2 = new ServletInfo("test", "/test", 4, Collections.<String, String> emptyMap());
+ final ServletInfo info1 = new ServletInfo("test", "/test", Collections.<String, String> emptyMap());
+ final ServletInfo info2 = new ServletInfo("test", "/test", Collections.<String, String> emptyMap());
final FailureStateHandler handler = new FailureStateHandler();
handler.add(info1, 1L, DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE);