FELIX-4545 : Implement Servlet Context Helper
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1655989 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 535ad38..75a9532 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
@@ -30,6 +30,7 @@
import org.apache.felix.http.base.internal.listener.ServletRequestAttributeListenerManager;
import org.apache.felix.http.base.internal.listener.ServletRequestListenerManager;
import org.apache.felix.http.base.internal.service.HttpServiceFactory;
+import org.apache.felix.http.base.internal.service.HttpServiceImpl;
import org.apache.felix.http.base.internal.service.HttpServiceRuntimeImpl;
import org.apache.felix.http.base.internal.whiteboard.ExtenderManager;
import org.osgi.framework.BundleContext;
@@ -143,7 +144,7 @@
HttpServiceFactory factory = new HttpServiceFactory(servletContext, this.registry, this.contextAttributeListener, this.sharedContextAttributes);
this.serviceReg = this.bundleContext.registerService(ifaces, factory, this.serviceProps);
- this.manager = new ExtenderManager((HttpService)factory.getService(this.bundleContext.getBundle(), this.serviceReg), this.bundleContext);
+ this.manager = new ExtenderManager((HttpServiceImpl)factory.getService(this.bundleContext.getBundle(), this.serviceReg), this.bundleContext);
this.runtimeReg = this.bundleContext.registerService(HttpServiceRuntime.class, new HttpServiceRuntimeImpl(), null);
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java
index 3a33ef6..dc61cd4 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java
@@ -17,7 +17,9 @@
package org.apache.felix.http.base.internal.handler;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.Iterator;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -25,6 +27,7 @@
import javax.servlet.Servlet;
import javax.servlet.ServletException;
+import org.apache.felix.http.base.internal.runtime.ServletInfo;
import org.osgi.service.http.NamespaceException;
public final class HandlerRegistry
@@ -50,7 +53,8 @@
return filters;
}
- public void addServlet(ServletHandler handler) throws ServletException, NamespaceException
+ public void addServlet(final ServletHandler handler)
+ throws ServletException, NamespaceException
{
handler.init();
@@ -78,7 +82,37 @@
updateFilterArray();
}
- public void removeServlet(Servlet servlet, final boolean destroy)
+ public Set<Servlet> removeServlet(final ServletInfo servletInfo, final boolean destroy)
+ {
+ final Set<Servlet> servletInstances = new HashSet<Servlet>();
+ boolean update = false;
+ for (Iterator<ServletHandler> it = aliasMap.values().iterator(); it.hasNext(); )
+ {
+ final ServletHandler handler = it.next();
+ if (handler.getServletInfo().compareTo(servletInfo) == 0 ) {
+ it.remove();
+ servletInstances.add(handler.getServlet());
+ if (destroy)
+ {
+ handler.destroy();
+ }
+ update = true;
+ }
+ }
+ if ( update )
+ {
+ updateServletArray();
+ }
+
+ return servletInstances;
+ }
+
+ /**
+ * Support for old Http Service registrations
+ * @param servlet
+ * @param destroy
+ */
+ public void removeServlet(final Servlet servlet, final boolean destroy)
{
boolean update = false;
for (Iterator<ServletHandler> it = aliasMap.values().iterator(); it.hasNext(); )
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
index e88cfc4..65ad762 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
@@ -235,29 +235,29 @@
}
}
+ private final ServletInfo servletInfo;
+
private final Servlet servlet;
- private final Pattern[] patterns;
+
+ private final Pattern pattern;
private final String alias;
public ServletHandler(final ExtServletContext context,
- final ServletInfo servletInfo)
+ final ServletInfo servletInfo,
+ final Servlet servlet,
+ final String alias)
{
super(context, servletInfo.getInitParams(), servletInfo.getName());
- this.servlet = servletInfo.getServlet();
- this.patterns = new Pattern[servletInfo.getPatterns().length];
- for(int i=0; i<servletInfo.getPatterns().length;i++)
- {
- this.patterns[i] = Pattern.compile(servletInfo.getPatterns()[i].replace(".", "\\.").replace("*", ".*"));
- }
- // TODO - currently we just provide one
- this.alias = servletInfo.getPatterns()[0];
+ this.servlet = servlet;
+ this.pattern = Pattern.compile(alias.replace(".", "\\.").replace("*", ".*"));
+ this.alias = alias;
+ this.servletInfo = servletInfo;
}
@Override
public int compareTo(ServletHandler other)
{
- // TODO - currently we just compare based on the first one
int result = other.alias.length() - this.alias.length();
if ( result == 0 )
{
@@ -342,8 +342,12 @@
{
return true;
}
- // TODO only first pattern is used
- return this.patterns[0].matcher(uri).matches();
+ return this.pattern.matcher(uri).matches();
+ }
+
+ public ServletInfo getServletInfo()
+ {
+ return this.servletInfo;
}
final void doHandle(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
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 fbb8ddb..b352faf 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
@@ -76,7 +76,7 @@
private final Servlet servlet;
- public ServletInfo(final ServiceReference<Servlet> ref, final Servlet servlet)
+ public ServletInfo(final ServiceReference<Servlet> ref)
{
super(ref);
this.name = getStringProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME);
@@ -85,7 +85,7 @@
this.asyncSupported = getBooleanProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED);
this.initParams = getInitParams(ref, SERVLET_INIT_PREFIX);
this.context = null;
- this.servlet = servlet;
+ this.servlet = 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 8c98d51..64cc5a8 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
@@ -21,6 +21,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import javax.servlet.Filter;
@@ -207,18 +208,31 @@
throw new IllegalArgumentException("ServletInfo must at least have one pattern or error page!");
}
- final ServletHandler handler = new ServletHandler(getServletContext(servletInfo.getContext()), servletInfo);
- try {
- this.handlerRegistry.addServlet(handler);
- } catch (ServletException e) {
- // TODO create failure DTO
- } catch (NamespaceException e) {
- // TODO create failure DTO
+ for(final String alias : servletInfo.getPatterns())
+ {
+ // create a handler for each alias
+ Servlet servlet = servletInfo.getServlet();
+ if ( servlet == null )
+ {
+ servlet = this.bundle.getBundleContext().getServiceObjects(servletInfo.getServiceReference()).getService();
+ // TODO - handle null
+ }
+ final ServletHandler handler = new ServletHandler(getServletContext(servletInfo.getContext()),
+ servletInfo,
+ servlet,
+ alias);
+ try {
+ this.handlerRegistry.addServlet(handler);
+ } catch (ServletException e) {
+ // TODO create failure DTO
+ } catch (NamespaceException e) {
+ // TODO create failure DTO
+ }
+ this.localServlets.add(servlet);
}
- this.localServlets.add(servletInfo.getServlet());
}
- public void unregisterServlet(final Servlet servlet, final ServletInfo servletInfo)
+ public void unregisterServlet(final ServletInfo servletInfo)
{
if (servletInfo == null)
{
@@ -226,8 +240,11 @@
}
if ( servletInfo.getPatterns() != null )
{
- this.handlerRegistry.removeServlet(servlet, true);
- this.localServlets.remove(servlet);
+ final Set<Servlet> instances = this.handlerRegistry.removeServlet(servletInfo, true);
+ for(final Servlet servlet : instances)
+ {
+ this.localServlets.remove(servlet);
+ }
}
}
@@ -245,7 +262,8 @@
* @see org.osgi.service.http.HttpService#registerServlet(java.lang.String, javax.servlet.Servlet, java.util.Dictionary, org.osgi.service.http.HttpContext)
*/
@Override
- public void registerServlet(String alias, Servlet servlet, Dictionary initParams, HttpContext context) throws ServletException, NamespaceException
+ public void registerServlet(String alias, Servlet servlet, Dictionary initParams, HttpContext context)
+ throws ServletException, NamespaceException
{
if (servlet == null)
{
@@ -326,9 +344,18 @@
* @see org.apache.felix.http.api.ExtHttpService#unregisterServlet(javax.servlet.Servlet)
*/
@Override
- public void unregisterServlet(Servlet servlet)
+ public void unregisterServlet(final Servlet servlet)
{
- unregisterServlet(servlet, true);
+ this.unregisterServlet(servlet, true);
+ }
+
+ private void unregisterServlet(final Servlet servlet, final boolean destroy)
+ {
+ if ( servlet != null )
+ {
+ this.handlerRegistry.removeServlet(servlet, destroy);
+ this.localServlets.remove(servlet);
+ }
}
private ExtServletContext getServletContext(HttpContext context)
@@ -365,15 +392,6 @@
}
}
- private void unregisterServlet(Servlet servlet, final boolean destroy)
- {
- if (servlet != null)
- {
- this.handlerRegistry.removeServlet(servlet, destroy);
- this.localServlets.remove(servlet);
- }
- }
-
private boolean isAliasValid(String alias)
{
if (alias == null)
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ExtenderManager.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ExtenderManager.java
index 0cd0dc9..bc9e4c1 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ExtenderManager.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ExtenderManager.java
@@ -23,11 +23,9 @@
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
-import javax.servlet.Servlet;
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;
import org.apache.felix.http.base.internal.service.HttpServiceImpl;
import org.apache.felix.http.base.internal.whiteboard.tracker.FilterTracker;
import org.apache.felix.http.base.internal.whiteboard.tracker.ServletContextHelperTracker;
@@ -64,13 +62,13 @@
private final ArrayList<ServiceTracker<?, ?>> trackers = new ArrayList<ServiceTracker<?, ?>>();
- public ExtenderManager(final HttpService httpService, final BundleContext bundleContext)
+ public ExtenderManager(final HttpServiceImpl httpService, final BundleContext bundleContext)
{
this.mapping = new HashMap<String, AbstractMapping>();
- this.contextManager = new ServletContextHelperManager();
+ this.contextManager = new ServletContextHelperManager(httpService);
this.httpService = httpService;
addTracker(new FilterTracker(bundleContext, this));
- addTracker(new ServletTracker(bundleContext, this));
+ addTracker(new ServletTracker(bundleContext, this.contextManager));
addTracker(new ServletContextHelperTracker(bundleContext, this.contextManager));
}
@@ -272,19 +270,6 @@
return filterInfo;
}
- public void addServlet(final Servlet service, final ServiceReference<Servlet> ref)
- {
- final ServletInfo servletInfo = new ServletInfo(ref, service);
- if ( servletInfo.isValid() )
- {
- ((HttpServiceImpl)this.httpService).registerServlet(servletInfo);
- }
- else
- {
- SystemLogger.debug("Ignoring Servlet Service " + ref);
- }
- }
-
public void removeFilter(final Filter service, ServiceReference<Filter> ref)
{
final FilterInfo filterInfo = createFilterInfo(ref, false);
@@ -294,15 +279,6 @@
}
}
- public void removeServlet(final Servlet service, final ServiceReference<Servlet> ref)
- {
- final ServletInfo servletInfo = new ServletInfo(ref, null);
- if ( servletInfo.isValid() )
- {
- ((HttpServiceImpl)this.httpService).unregisterServlet(service, servletInfo);
- }
- }
-
private synchronized void unregisterAll()
{
AbstractMapping[] mappings = null;
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 d51fbe9..bc35748 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
@@ -24,17 +24,23 @@
import java.util.Map;
import org.apache.felix.http.base.internal.runtime.ContextInfo;
+import org.apache.felix.http.base.internal.runtime.ServletInfo;
+import org.apache.felix.http.base.internal.service.HttpServiceImpl;
public final class ServletContextHelperManager
{
private final Map<String, List<ContextHolder>> nameMap = new HashMap<String, List<ContextHolder>>();
+ private final HttpServiceImpl httpService;
+
/**
* Create a new servlet context helper manager
* and the default context
*/
- public ServletContextHelperManager()
+ public ServletContextHelperManager(final HttpServiceImpl httpService)
{
+ this.httpService = httpService;
+
// create default context
final ContextInfo info = new ContextInfo();
this.addContextHelper(info);
@@ -126,6 +132,16 @@
}
}
+ public void addServlet(final ServletInfo servletInfo)
+ {
+ this.httpService.registerServlet(servletInfo);
+ }
+
+ public void removeServlet(final ServletInfo servletInfo)
+ {
+ this.httpService.unregisterServlet(servletInfo);
+ }
+
private final static class ContextHolder implements Comparable<ContextHolder>
{
private final ContextInfo info;
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletTracker.java
index de944db..fe89b1e 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletTracker.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletTracker.java
@@ -18,15 +18,17 @@
import javax.servlet.Servlet;
-import org.apache.felix.http.base.internal.whiteboard.ExtenderManager;
+import org.apache.felix.http.base.internal.logger.SystemLogger;
+import org.apache.felix.http.base.internal.runtime.ServletInfo;
+import org.apache.felix.http.base.internal.whiteboard.ServletContextHelperManager;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
-public final class ServletTracker extends AbstractTracker<Servlet>
+public final class ServletTracker extends AbstractReferenceTracker<Servlet>
{
- private final ExtenderManager manager;
+ private final ServletContextHelperManager contextManager;
private static org.osgi.framework.Filter createFilter(final BundleContext btx)
{
@@ -43,28 +45,35 @@
return null; // we never get here - and if we get an NPE which is fine
}
- public ServletTracker(final BundleContext context, final ExtenderManager manager)
+ public ServletTracker(final BundleContext context, final ServletContextHelperManager manager)
{
super(context, createFilter(context));
- this.manager = manager;
+ this.contextManager = manager;
}
@Override
- protected void added(Servlet service, ServiceReference ref)
+ protected void added(final ServiceReference<Servlet> ref)
{
- this.manager.addServlet(service, ref);
+ final ServletInfo info = new ServletInfo(ref);
+
+ if ( info.isValid() )
+ {
+ this.contextManager.addServlet(info);
+ }
+ else
+ {
+ SystemLogger.debug("Ignoring Servlet service " + ref);
+ }
}
@Override
- protected void modified(Servlet service, ServiceReference ref)
+ protected void removed(final ServiceReference<Servlet> ref)
{
- removed(service, ref);
- added(service, ref);
- }
+ final ServletInfo info = new ServletInfo(ref);
- @Override
- protected void removed(Servlet service, ServiceReference ref)
- {
- this.manager.removeServlet(service, ref);
+ if ( info.isValid() )
+ {
+ this.contextManager.removeServlet(info);
+ }
}
}
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/handler/HandlerRegistryTest.java b/http/base/src/test/java/org/apache/felix/http/base/internal/handler/HandlerRegistryTest.java
index d1492ba..93bb41f 100644
--- a/http/base/src/test/java/org/apache/felix/http/base/internal/handler/HandlerRegistryTest.java
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/handler/HandlerRegistryTest.java
@@ -44,7 +44,7 @@
Servlet servlet = Mockito.mock(Servlet.class);
final ServletInfo info = new ServletInfo("foo", "/foo", 0, null, servlet, null);
- ServletHandler handler = new ServletHandler(null, info);
+ ServletHandler handler = new ServletHandler(null, info, info.getServlet(), info.getPatterns()[0]);
assertEquals("Precondition", 0, hr.getServlets().length);
hr.addServlet(handler);
Mockito.verify(servlet, Mockito.times(1)).init(Mockito.any(ServletConfig.class));
@@ -52,7 +52,7 @@
assertSame(handler, hr.getServlets()[0]);
final ServletInfo info2 = new ServletInfo("bar", "/bar", 0, null, servlet, null);
- ServletHandler handler2 = new ServletHandler(null, info2);
+ ServletHandler handler2 = new ServletHandler(null, info2, info2.getServlet(), info2.getPatterns()[0]);
try
{
hr.addServlet(handler2);
@@ -66,7 +66,7 @@
assertArrayEquals(new ServletHandler[] {handler2, handler}, hr.getServlets());
final ServletInfo info3 = new ServletInfo("zar", "/foo", 0, null, Mockito.mock(Servlet.class), null);
- ServletHandler handler3 = new ServletHandler(null,info3);
+ ServletHandler handler3 = new ServletHandler(null,info3, info3.getServlet(), info3.getPatterns()[0]);
try
{
@@ -93,7 +93,7 @@
Servlet servlet = Mockito.mock(Servlet.class);
final ServletInfo info = new ServletInfo("bar", "/bar", 0, null, servlet, null);
- final ServletHandler otherHandler = new ServletHandler(null, info);
+ final ServletHandler otherHandler = new ServletHandler(null, info, info.getServlet(), info.getPatterns()[0]);
Mockito.doAnswer(new Answer<Void>()
{
@@ -113,7 +113,7 @@
}).when(servlet).init(Mockito.any(ServletConfig.class));
final ServletInfo info2 = new ServletInfo("foo", "/foo", 0, null, servlet, null);
- ServletHandler handler = new ServletHandler(null, info2);
+ ServletHandler handler = new ServletHandler(null, info2, info2.getServlet(), info2.getPatterns()[0]);
try
{
hr.addServlet(handler);
@@ -137,7 +137,7 @@
Servlet otherServlet = Mockito.mock(Servlet.class);
final ServletInfo info = new ServletInfo("bar", "/foo", 0, null, otherServlet, null);
- final ServletHandler otherHandler = new ServletHandler(null, info);
+ final ServletHandler otherHandler = new ServletHandler(null, info, info.getServlet(), info.getPatterns()[0]);
Servlet servlet = Mockito.mock(Servlet.class);
Mockito.doAnswer(new Answer<Void>()
@@ -152,7 +152,7 @@
}).when(servlet).init(Mockito.any(ServletConfig.class));
final ServletInfo info2 = new ServletInfo("foo", "/foo", 0, null, servlet, null);
- ServletHandler handler = new ServletHandler(null, info2);
+ ServletHandler handler = new ServletHandler(null, info2, info2.getServlet(), info2.getPatterns()[0]);
try
{
@@ -264,11 +264,11 @@
Servlet servlet = Mockito.mock(Servlet.class);
final ServletInfo info = new ServletInfo("f", "/f", 0, null, servlet, null);
- ServletHandler servletHandler = new ServletHandler(null, info);
+ ServletHandler servletHandler = new ServletHandler(null, info, info.getServlet(), info.getPatterns()[0]);
hr.addServlet(servletHandler);
Servlet servlet2 = Mockito.mock(Servlet.class);
final ServletInfo info2 = new ServletInfo("ff", "/ff", 0, null, servlet2, null);
- ServletHandler servletHandler2 = new ServletHandler(null, info2);
+ ServletHandler servletHandler2 = new ServletHandler(null, info2, info2.getServlet(), info2.getPatterns()[0]);
hr.addServlet(servletHandler2);
Filter filter = Mockito.mock(Filter.class);
final FilterInfo fi = new FilterInfo();
diff --git a/http/base/src/test/java/org/apache/felix/http/base/internal/handler/ServletHandlerTest.java b/http/base/src/test/java/org/apache/felix/http/base/internal/handler/ServletHandlerTest.java
index efabc00..0eeb909 100644
--- a/http/base/src/test/java/org/apache/felix/http/base/internal/handler/ServletHandlerTest.java
+++ b/http/base/src/test/java/org/apache/felix/http/base/internal/handler/ServletHandlerTest.java
@@ -231,6 +231,6 @@
private ServletHandler createHandler(String alias)
{
final ServletInfo info = new ServletInfo(null, alias, 0, null, this.servlet, null);
- return new ServletHandler(this.context, info);
+ return new ServletHandler(this.context, info, info.getServlet(), info.getPatterns()[0]);
}
}