FELIX-4060 : Implement HTTP Service Update (RFC-189) - fix broken HttpService implementation
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1656662 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/PerContextHandlerRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/PerContextHandlerRegistry.java
index 09d9ecb..4f34b90 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/PerContextHandlerRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/PerContextHandlerRegistry.java
@@ -31,7 +31,6 @@
import org.apache.felix.http.base.internal.runtime.FilterInfo;
import org.apache.felix.http.base.internal.runtime.ServletContextHelperInfo;
import org.apache.felix.http.base.internal.runtime.ServletInfo;
-import org.osgi.service.http.NamespaceException;
public final class PerContextHandlerRegistry implements Comparable<PerContextHandlerRegistry>
{
@@ -109,14 +108,8 @@
/**
* Add a new servlet.
*/
- public synchronized void addServlet(ServletContextHelperInfo contextInfo, ServletHandler handler) throws ServletException, NamespaceException
+ public synchronized void addServlet(final ServletHandler handler) throws ServletException
{
- if (this.servletMap.containsKey(handler.getServlet()))
- {
- // Do not destroy the servlet as the same instance was already registered
- throw new ServletException("Servlet instance " + handler.getName() + " already registered");
- }
-
// Can be null in case of error-handling servlets...
String[] patterns = handler.getServletInfo().getPatterns();
int length = patterns == null ? 0 : patterns.length;
@@ -189,11 +182,6 @@
return result.toArray(new FilterHandler[result.size()]);
}
- public synchronized Servlet getServletByAlias(String alias)
- {
- return this.servletPatternMap.get(alias);
- }
-
public ServletHandler getServletHandlerByName(String name)
{
return this.servletMapping.getByName(name);
@@ -260,7 +248,7 @@
return null;
}
- public synchronized Servlet removeServlet(final ServletContextHelperInfo contextInfo, ServletInfo servletInfo, final boolean destroy)
+ public synchronized Servlet removeServlet(ServletInfo servletInfo, final boolean destroy)
{
for(final ServletHandler handler : this.servletMap.values())
{
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 f2aab64..feed6a9 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
@@ -108,7 +108,7 @@
{
super(serviceRanking);
this.name = name;
- this.patterns = new String[] {pattern};
+ this.patterns = new String[] {pattern, pattern + "/*"};
this.initParams = initParams;
this.asyncSupported = false;
this.errorPage = null;
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/HttpServiceImpl.java
index 9062128..255c3a8 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/HttpServiceImpl.java
@@ -20,7 +20,9 @@
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.Map;
+import java.util.Set;
import javax.servlet.Filter;
import javax.servlet.Servlet;
@@ -45,16 +47,16 @@
{
private final Bundle bundle;
private final PerContextHandlerRegistry handlerRegistry;
- private final HashSet<Servlet> localServlets;
- private final HashSet<Filter> localFilters;
+ 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>();
+
public HttpServiceImpl(Bundle bundle, ServletContext context, PerContextHandlerRegistry handlerRegistry, ServletContextAttributeListener servletAttributeListener, boolean sharedContextAttributes)
{
this.bundle = bundle;
this.handlerRegistry = handlerRegistry;
- this.localServlets = new HashSet<Servlet>();
- this.localFilters = new HashSet<Filter>();
this.contextManager = new ServletContextManager(this.bundle, context, servletAttributeListener, sharedContextAttributes);
}
@@ -108,14 +110,19 @@
this.localFilters.add(filter);
}
+ /**
+ * No need to sync this method, syncing is done via {@link #registerServlet(String, Servlet, Dictionary, HttpContext)}
+ * @see org.osgi.service.http.HttpService#registerResources(java.lang.String, java.lang.String, org.osgi.service.http.HttpContext)
+ */
@Override
- public void registerResources(String alias, String name, HttpContext context) throws NamespaceException
+ public void registerResources(final String alias, final String name, final HttpContext context) throws NamespaceException
{
if (!isNameValid(name))
{
throw new IllegalArgumentException("Malformed resource name [" + name + "]");
}
+ // TODO - check validity of alias
try
{
Servlet servlet = new ResourceServlet(name);
@@ -160,56 +167,62 @@
}
final ServletInfo servletInfo = new ServletInfo(null, alias, 0, paramMap);
-
final ExtServletContext httpContext = getServletContext(context);
final ServletHandler handler = new ServletHandler(null,
httpContext,
servletInfo,
servlet);
- try {
- this.handlerRegistry.addServlet(null, handler);
- } catch (ServletException e) {
- // TODO create failure DTO
- } catch (NamespaceException e) {
- // TODO create failure DTO
- }
- this.localServlets.add(servlet);
+ synchronized ( this.aliasMap )
+ {
+ if ( this.aliasMap.containsKey(alias) )
+ {
+ throw new NamespaceException("Alias " + alias + " is already in use.");
+ }
+ 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);
+ }
}
/**
* @see org.osgi.service.http.HttpService#unregister(java.lang.String)
*/
@Override
- public void unregister(String alias)
+ public void unregister(final String alias)
{
- final Servlet servlet = this.handlerRegistry.getServletByAlias(alias);
- if (servlet == null)
+ synchronized ( this.aliasMap )
{
- // FELIX-4561 - don't bother throwing an exception if we're stopping anyway...
- if ((bundle.getState() & Bundle.STOPPING) != 0)
- {
- throw new IllegalArgumentException("Nothing registered at " + alias);
- }
- else
- {
- SystemLogger.debug("Nothing registered at " + alias + "; ignoring this because the bundle is stopping!", null);
- }
- }
- unregisterServlet(servlet);
+ 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)
+ {
+ this.localServlets.remove(servlet);
+ }
+ }
}
public void unregisterAll()
{
- HashSet<Servlet> servlets = new HashSet<Servlet>(this.localServlets);
- for (Servlet servlet : servlets)
+ final Set<Servlet> servlets = new HashSet<Servlet>(this.localServlets);
+ for (final Servlet servlet : servlets)
{
unregisterServlet(servlet, false);
}
- HashSet<Filter> filters = new HashSet<Filter>(this.localFilters);
- for (Filter fiter : filters)
+ final Set<Filter> filters = new HashSet<Filter>(this.localFilters);
+ for (final Filter fiter : filters)
{
unregisterFilter(fiter, false);
}
@@ -240,7 +253,21 @@
if ( servlet != null )
{
this.handlerRegistry.removeServlet(servlet, destroy);
- this.localServlets.remove(servlet);
+ 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;
+ }
+
+ }
+ this.localServlets.remove(servlet);
+ }
}
}
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 8b7daca..d6f9c5d 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
@@ -36,7 +36,7 @@
import org.apache.felix.http.base.internal.whiteboard.tracker.ServletContextListenerTracker;
import org.apache.felix.http.base.internal.whiteboard.tracker.ServletTracker;
import org.osgi.framework.BundleContext;
-import org.osgi.service.http.NamespaceException;
+import org.osgi.framework.ServiceObjects;
import org.osgi.util.tracker.ServiceTracker;
public final class WhiteboardHttpService
@@ -94,20 +94,23 @@
public void registerServlet(@Nonnull final ContextHandler contextHandler,
@Nonnull final ServletInfo servletInfo)
{
- final Servlet servlet = this.bundleContext.getServiceObjects(servletInfo.getServiceReference()).getService();
- // TODO create failure DTO if null
- if ( servlet != null )
+ final ServiceObjects<Servlet> so = this.bundleContext.getServiceObjects(servletInfo.getServiceReference());
+ if ( so != null )
{
- final ServletHandler handler = new ServletHandler(contextHandler.getContextInfo(),
- contextHandler.getServletContext(servletInfo.getServiceReference().getBundle()),
- servletInfo,
- servlet);
- try {
- this.handlerRegistry.getRegistry(contextHandler.getContextInfo()).addServlet(contextHandler.getContextInfo(), handler);
- } catch (ServletException e) {
- // TODO create failure DTO
- } catch (NamespaceException e) {
- // TODO create failure DTO
+ final Servlet servlet = so.getService();
+ // TODO create failure DTO if null
+ if ( servlet != null )
+ {
+ final ServletHandler handler = new ServletHandler(contextHandler.getContextInfo(),
+ contextHandler.getServletContext(servletInfo.getServiceReference().getBundle()),
+ servletInfo,
+ servlet);
+ try {
+ this.handlerRegistry.getRegistry(contextHandler.getContextInfo()).addServlet(handler);
+ } catch (final ServletException e) {
+ so.ungetService(servlet);
+ // TODO create failure DTO
+ }
}
}
}
@@ -119,7 +122,7 @@
*/
public void unregisterServlet(@Nonnull final ContextHandler contextHandler, @Nonnull final ServletInfo servletInfo)
{
- final Servlet instance = this.handlerRegistry.getRegistry(contextHandler.getContextInfo()).removeServlet(contextHandler.getContextInfo(), servletInfo, true);
+ final Servlet instance = this.handlerRegistry.getRegistry(contextHandler.getContextInfo()).removeServlet(servletInfo, true);
if ( instance != null )
{
this.bundleContext.getServiceObjects(servletInfo.getServiceReference()).ungetService(instance);
@@ -182,11 +185,9 @@
servletInfo,
servlet);
try {
- this.handlerRegistry.getRegistry(contextHandler.getContextInfo()).addServlet(contextHandler.getContextInfo(), handler);
+ this.handlerRegistry.getRegistry(contextHandler.getContextInfo()).addServlet(handler);
} catch (ServletException e) {
// TODO create failure DTO
- } catch (NamespaceException e) {
- // TODO create failure DTO
}
}