FELIX-4060 : Split implementation of http service into shared and per bundle part.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1661355 13f79535-47bb-0310-9956-ffa450edef68
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 23d95ee..1d3c057 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
@@ -64,7 +64,6 @@
private static final String OBSOLETE_REG_PROPERTY_ENDPOINTS = "osgi.http.service.endpoints";
private final BundleContext bundleContext;
- private final HandlerRegistry handlerRegistry;
private final boolean sharedContextAttributes;
private final ServletContextAttributeListenerManager contextAttributeListenerManager;
@@ -77,6 +76,9 @@
private volatile ServletContext context;
private volatile ServiceRegistration<?> httpServiceReg;
+ private final HandlerRegistry handlerRegistry;
+ private volatile SharedHttpServiceImpl sharedHttpService;
+
public HttpServiceFactory(final BundleContext bundleContext,
final HandlerRegistry handlerRegistry)
{
@@ -100,6 +102,8 @@
this.sessionListenerManager.open();
this.sessionAttributeListenerManager.open();
+ this.sharedHttpService = new SharedHttpServiceImpl(handlerRegistry.getRegistry(null));
+
final String[] ifaces = new String[] { HttpService.class.getName(), ExtHttpService.class.getName() };
this.httpServiceReg = bundleContext.registerService(ifaces, this, this.httpServiceProps);
}
@@ -113,6 +117,8 @@
this.httpServiceReg = null;
}
+ this.sharedHttpService = null;
+
this.contextAttributeListenerManager.close();
this.requestListenerManager.close();
this.requestAttributeListenerManager.close();
@@ -123,8 +129,9 @@
@Override
public HttpService getService(final Bundle bundle, final ServiceRegistration<HttpService> reg)
{
- return new HttpServiceImpl(bundle, this.context,
- this.handlerRegistry.getRegistry(null),
+ return new PerBundleHttpServiceImpl(bundle,
+ this.sharedHttpService,
+ this.context,
this.contextAttributeListenerManager,
this.sharedContextAttributes,
this.requestListenerManager,
@@ -135,9 +142,9 @@
public void ungetService(final Bundle bundle, final ServiceRegistration<HttpService> reg,
final HttpService service)
{
- if ( service instanceof HttpServiceImpl )
+ if ( service instanceof PerBundleHttpServiceImpl )
{
- ((HttpServiceImpl)service).unregisterAll();
+ ((PerBundleHttpServiceImpl)service).unregisterAll();
}
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/service/PerBundleHttpServiceImpl.java
similarity index 75%
rename from http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java
rename to http/base/src/main/java/org/apache/felix/http/base/internal/service/PerBundleHttpServiceImpl.java
index bb5a128..7634f39 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/service/PerBundleHttpServiceImpl.java
@@ -20,7 +20,6 @@
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.Map;
import java.util.Set;
@@ -34,9 +33,6 @@
import org.apache.felix.http.api.ExtHttpService;
import org.apache.felix.http.base.internal.context.ExtServletContext;
-import org.apache.felix.http.base.internal.handler.FilterHandler;
-import org.apache.felix.http.base.internal.handler.PerContextHandlerRegistry;
-import org.apache.felix.http.base.internal.handler.ServletHandler;
import org.apache.felix.http.base.internal.logger.SystemLogger;
import org.apache.felix.http.base.internal.runtime.FilterInfo;
import org.apache.felix.http.base.internal.runtime.ServletInfo;
@@ -44,16 +40,26 @@
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.NamespaceException;
-public final class HttpServiceImpl implements ExtHttpService
+/**
+ * This implementation of the {@link ExtHttpService} implements the front end
+ * used by client bundles. It performs the validity checks and passes the
+ * real operation to the shared http service.
+ */
+public final class PerBundleHttpServiceImpl implements ExtHttpService
{
private final Bundle bundle;
- private final PerContextHandlerRegistry handlerRegistry;
private final Set<Servlet> localServlets = new HashSet<Servlet>();
private final Set<Filter> localFilters = new HashSet<Filter>();
private final ServletContextManager contextManager;
- private final Map<String, ServletHandler> aliasMap = new HashMap<String, ServletHandler>();
+ private final SharedHttpServiceImpl sharedHttpService;
- public HttpServiceImpl(Bundle bundle, ServletContext context, PerContextHandlerRegistry handlerRegistry, ServletContextAttributeListener servletAttributeListener, boolean sharedContextAttributes, ServletRequestListener reqListener, ServletRequestAttributeListener reqAttrListener)
+ public PerBundleHttpServiceImpl(final Bundle bundle,
+ final SharedHttpServiceImpl sharedHttpService,
+ final ServletContext context,
+ final ServletContextAttributeListener servletAttributeListener,
+ final boolean sharedContextAttributes,
+ final ServletRequestListener reqListener,
+ final ServletRequestAttributeListener reqAttrListener)
{
if (bundle == null)
{
@@ -63,14 +69,10 @@
{
throw new IllegalArgumentException("Context cannot be null!");
}
- if (handlerRegistry == null)
- {
- throw new IllegalArgumentException("HandlerRegistry cannot be null!");
- }
this.bundle = bundle;
- this.handlerRegistry = handlerRegistry;
this.contextManager = new ServletContextManager(this.bundle, context, servletAttributeListener, sharedContextAttributes, reqListener, reqAttrListener);
+ this.sharedHttpService = sharedHttpService;
}
@Override
@@ -83,7 +85,12 @@
* @see org.apache.felix.http.api.ExtHttpService#registerFilter(javax.servlet.Filter, java.lang.String, java.util.Dictionary, int, org.osgi.service.http.HttpContext)
*/
@Override
- public void registerFilter(Filter filter, String pattern, Dictionary initParams, int ranking, HttpContext context) throws ServletException
+ public void registerFilter(final Filter filter,
+ final String pattern,
+ final Dictionary initParams,
+ final int ranking,
+ final HttpContext context)
+ throws ServletException
{
if (filter == null)
{
@@ -114,16 +121,13 @@
final ExtServletContext httpContext = getServletContext(context);
- FilterHandler handler = new FilterHandler(null, httpContext, filter, filterInfo);
- try
+ if ( this.sharedHttpService.registerFilter(httpContext, filter, filterInfo) )
{
- this.handlerRegistry.addFilter(handler);
+ synchronized ( this.localFilters )
+ {
+ this.localFilters.add(filter);
+ }
}
- catch (ServletException e)
- {
- // TODO create failure DTO
- }
- this.localFilters.add(filter);
}
/**
@@ -181,26 +185,33 @@
}
}
+ synchronized (this.localServlets)
+ {
+ if (this.localServlets.contains(servlet))
+ {
+ throw new ServletException("Servlet instance " + servlet + " already registered");
+ }
+ this.localServlets.add(servlet);
+ }
+
final ServletInfo servletInfo = new ServletInfo(String.format("%s_%d", servlet.getClass(), this.hashCode()), alias, 0, paramMap);
final ExtServletContext httpContext = getServletContext(context);
- final ServletHandler handler = new ServletHandler(null, httpContext, servletInfo, servlet);
-
- synchronized (this.aliasMap)
+ boolean success = false;
+ try
{
- if (this.aliasMap.containsKey(alias))
+ this.sharedHttpService.registerServlet(alias, httpContext, servlet, servletInfo);
+ success = true;
+ }
+ finally
+ {
+ if ( !success )
{
- throw new NamespaceException("Alias " + alias + " is already in use.");
+ synchronized ( this.localServlets )
+ {
+ this.localServlets.remove(servlet);
+ }
}
- if (this.localServlets.contains(servlet))
- {
- throw new ServletException("Servlet instance " + handler.getName() + " already registered");
- }
-
- this.handlerRegistry.addServlet(handler);
-
- this.aliasMap.put(alias, handler);
- this.localServlets.add(servlet);
}
}
@@ -210,15 +221,10 @@
@Override
public void unregister(final String alias)
{
- synchronized (this.aliasMap)
+ final Servlet servlet = this.sharedHttpService.unregister(alias);
+ if ( servlet != null )
{
- final ServletHandler handler = this.aliasMap.remove(alias);
- if (handler == null)
- {
- throw new IllegalArgumentException("Nothing registered at " + alias);
- }
- final Servlet servlet = this.handlerRegistry.removeServlet(handler.getServletInfo(), true);
- if (servlet != null)
+ synchronized ( this.localServlets )
{
this.localServlets.remove(servlet);
}
@@ -245,9 +251,9 @@
* @see org.apache.felix.http.api.ExtHttpService#unregisterFilter(javax.servlet.Filter)
*/
@Override
- public void unregisterFilter(Filter filter)
+ public void unregisterFilter(final Filter filter)
{
- unregisterFilter(filter, true);
+ this.unregisterFilter(filter, true);
}
/**
@@ -264,22 +270,11 @@
{
if (servlet != null)
{
- this.handlerRegistry.removeServlet(servlet, destroy);
- synchronized (this.aliasMap)
+ synchronized ( this.localServlets )
{
- final Iterator<Map.Entry<String, ServletHandler>> i = this.aliasMap.entrySet().iterator();
- while (i.hasNext())
- {
- final Map.Entry<String, ServletHandler> entry = i.next();
- if (entry.getValue().getServlet() == servlet)
- {
- i.remove();
- break;
- }
-
- }
this.localServlets.remove(servlet);
}
+ this.sharedHttpService.unregisterServlet(servlet, destroy);
}
}
@@ -293,7 +288,19 @@
return this.contextManager.getServletContext(context);
}
- private boolean isNameValid(String name)
+ private void unregisterFilter(Filter filter, final boolean destroy)
+ {
+ if (filter != null)
+ {
+ synchronized ( this.localFilters )
+ {
+ this.localFilters.remove(filter);
+ }
+ this.sharedHttpService.unregisterFilter(filter, destroy);
+ }
+ }
+
+ private boolean isNameValid(final String name)
{
if (name == null)
{
@@ -308,15 +315,6 @@
return true;
}
- private void unregisterFilter(Filter filter, final boolean destroy)
- {
- if (filter != null)
- {
- this.handlerRegistry.removeFilter(filter, destroy);
- this.localFilters.remove(filter);
- }
- }
-
private boolean isAliasValid(final String alias)
{
if (alias == null)
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/SharedHttpServiceImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/service/SharedHttpServiceImpl.java
new file mode 100644
index 0000000..fc20fe8
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/service/SharedHttpServiceImpl.java
@@ -0,0 +1,139 @@
+/*
+ * 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.service;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.servlet.Filter;
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+
+import org.apache.felix.http.base.internal.context.ExtServletContext;
+import org.apache.felix.http.base.internal.handler.FilterHandler;
+import org.apache.felix.http.base.internal.handler.PerContextHandlerRegistry;
+import org.apache.felix.http.base.internal.handler.ServletHandler;
+import org.apache.felix.http.base.internal.runtime.FilterInfo;
+import org.apache.felix.http.base.internal.runtime.ServletInfo;
+import org.osgi.service.http.NamespaceException;
+
+public final class SharedHttpServiceImpl
+{
+ private final PerContextHandlerRegistry handlerRegistry;
+
+ private final Map<String, ServletHandler> aliasMap = new HashMap<String, ServletHandler>();
+
+ public SharedHttpServiceImpl(final PerContextHandlerRegistry handlerRegistry)
+ {
+ if (handlerRegistry == null)
+ {
+ throw new IllegalArgumentException("HandlerRegistry cannot be null!");
+ }
+
+ this.handlerRegistry = handlerRegistry;
+ }
+
+ /**
+ * Register a filter
+ */
+ public boolean registerFilter(@Nonnull final ExtServletContext httpContext,
+ @Nonnull final Filter filter,
+ @Nonnull final FilterInfo filterInfo)
+ {
+ final FilterHandler handler = new FilterHandler(null, httpContext, filter, filterInfo);
+ try
+ {
+ this.handlerRegistry.addFilter(handler);
+ return true;
+ }
+ catch (final ServletException e)
+ {
+ // TODO create failure DTO
+ }
+ return false;
+ }
+
+ /**
+ * Register a servlet
+ */
+ public void registerServlet(@Nonnull final String alias,
+ @Nonnull final ExtServletContext httpContext,
+ @Nonnull final Servlet servlet,
+ @Nonnull final ServletInfo servletInfo) throws ServletException, NamespaceException
+ {
+ final ServletHandler handler = new ServletHandler(null, httpContext, servletInfo, servlet);
+
+ synchronized (this.aliasMap)
+ {
+ if (this.aliasMap.containsKey(alias))
+ {
+ throw new NamespaceException("Alias " + alias + " is already in use.");
+ }
+ this.handlerRegistry.addServlet(handler);
+
+ this.aliasMap.put(alias, handler);
+ }
+ }
+
+ /**
+ * @see org.osgi.service.http.HttpService#unregister(java.lang.String)
+ */
+ public Servlet unregister(final String alias)
+ {
+ synchronized (this.aliasMap)
+ {
+ final ServletHandler handler = this.aliasMap.remove(alias);
+ if (handler == null)
+ {
+ throw new IllegalArgumentException("Nothing registered at " + alias);
+ }
+ return this.handlerRegistry.removeServlet(handler.getServletInfo(), true);
+ }
+ }
+
+ public void unregisterServlet(final Servlet servlet, final boolean destroy)
+ {
+ if (servlet != null)
+ {
+ this.handlerRegistry.removeServlet(servlet, destroy);
+ synchronized (this.aliasMap)
+ {
+ final Iterator<Map.Entry<String, ServletHandler>> i = this.aliasMap.entrySet().iterator();
+ while (i.hasNext())
+ {
+ final Map.Entry<String, ServletHandler> entry = i.next();
+ if (entry.getValue().getServlet() == servlet)
+ {
+ i.remove();
+ break;
+ }
+
+ }
+ }
+ }
+ }
+
+ public void unregisterFilter(final Filter filter, final boolean destroy)
+ {
+ if (filter != null)
+ {
+ this.handlerRegistry.removeFilter(filter, destroy);
+ }
+ }
+}