FELIX-4545 : Implement Servlet Context Helper, more refactoring, add support for ServletContextListener services
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1656283 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 1cf76da..af79bb4 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
@@ -31,8 +31,7 @@
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.HttpServiceRuntimeImpl;
-import org.apache.felix.http.base.internal.service.InternalHttpService;
-import org.apache.felix.http.base.internal.whiteboard.ExtenderManager;
+import org.apache.felix.http.base.internal.whiteboard.WhiteboardHttpService;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.http.HttpService;
@@ -71,7 +70,7 @@
private final HttpSessionAttributeListenerManager sessionAttributeListener;
private final boolean sharedContextAttributes;
private final HttpServicePlugin plugin;
- private volatile ExtenderManager manager;
+ private volatile WhiteboardHttpService whiteboardHttpService;
private volatile ServiceRegistration serviceReg;
private volatile ServiceRegistration<HttpServiceRuntime> runtimeReg;
@@ -144,17 +143,17 @@
HttpServiceFactory factory = new HttpServiceFactory(servletContext, this.registry, this.contextAttributeListener, this.sharedContextAttributes);
this.serviceReg = this.bundleContext.registerService(ifaces, factory, this.serviceProps);
- this.manager = new ExtenderManager(new InternalHttpService(this.bundleContext, servletContext, this.registry), this.bundleContext);
+ this.whiteboardHttpService = new WhiteboardHttpService(this.bundleContext, servletContext, this.registry);
this.runtimeReg = this.bundleContext.registerService(HttpServiceRuntime.class, new HttpServiceRuntimeImpl(), null);
}
public void unregister()
{
- if ( this.manager != null )
+ if ( this.whiteboardHttpService != null )
{
- this.manager.close();
- this.manager = null;
+ this.whiteboardHttpService.close();
+ this.whiteboardHttpService = null;
}
if ( this.runtimeReg != null )
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ContextInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ContextInfo.java
index 450b11f..62d0ee5 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ContextInfo.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ContextInfo.java
@@ -48,11 +48,24 @@
this.prefix = prefix;
}
+ private boolean isValidPath()
+ {
+ if ( !this.isEmpty(path) )
+ {
+ // TODO we need more validation
+ if ( path.startsWith("/") && path.endsWith("/") )
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public boolean isValid()
{
- // TODO - check if name and path are valid values
- return super.isValid() && !this.isEmpty(this.name) && !this.isEmpty(this.path);
+ // TODO - check if name has valid value
+ return super.isValid() && !this.isEmpty(this.name) && isValidPath();
}
public String getName()
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java
new file mode 100644
index 0000000..fe73d8e
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java
@@ -0,0 +1,36 @@
+/*
+ * 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.runtime;
+
+import javax.servlet.ServletContextListener;
+
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Info object for registered servlet context listeners
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public final class ServletContextListenerInfo extends WhiteboardServiceInfo<ServletContextListener>
+{
+ public ServletContextListenerInfo(final ServiceReference<ServletContextListener> ref)
+ {
+ super(ref);
+ }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/InternalHttpService.java b/http/base/src/main/java/org/apache/felix/http/base/internal/service/InternalHttpService.java
deleted file mode 100644
index 6b9d3b7..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/InternalHttpService.java
+++ /dev/null
@@ -1,211 +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.service;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.annotation.Nonnull;
-import javax.servlet.Filter;
-import javax.servlet.Servlet;
-import javax.servlet.ServletContext;
-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.HandlerRegistry;
-import org.apache.felix.http.base.internal.handler.ServletHandler;
-import org.apache.felix.http.base.internal.runtime.AbstractInfo;
-import org.apache.felix.http.base.internal.runtime.ContextInfo;
-import org.apache.felix.http.base.internal.runtime.FilterInfo;
-import org.apache.felix.http.base.internal.runtime.ResourceInfo;
-import org.apache.felix.http.base.internal.runtime.ServletInfo;
-import org.osgi.framework.BundleContext;
-import org.osgi.service.http.NamespaceException;
-import org.osgi.service.http.context.ServletContextHelper;
-
-public final class InternalHttpService
-{
-
- private final HandlerRegistry handlerRegistry;
-
- private final BundleContext bundleContext;
-
- private final ServletContext webContext;
-
- private static final class ContextHolder
- {
- public long counter;
- public ExtServletContext servletContext;
- public ServletContextHelper servletContextHelper;
- }
-
- private final Map<Long, ContextHolder> contextMap = new HashMap<Long, ContextHolder>();
-
- public InternalHttpService(final BundleContext bundleContext,
- final ServletContext context,
- final HandlerRegistry handlerRegistry)
- {
- this.handlerRegistry = handlerRegistry;
- this.bundleContext = bundleContext;
- this.webContext = context;
- }
-
- private ExtServletContext getServletContext(@Nonnull final ContextInfo contextInfo,
- @Nonnull final AbstractInfo<?> serviceInfo)
- {
- final Long key = contextInfo.getServiceId();
- synchronized ( this.contextMap )
- {
- ContextHolder holder = this.contextMap.get(key);
- if ( holder == null )
- {
- holder = new ContextHolder();
- // TODO check for null
- holder.servletContextHelper = serviceInfo.getServiceReference().getBundle().getBundleContext()
- .getServiceObjects(contextInfo.getServiceReference()).getService();
- holder.servletContext = new ServletContextImpl(serviceInfo.getServiceReference().getBundle(),
- this.webContext,
- holder.servletContextHelper);
- }
- holder.counter++;
-
- return holder.servletContext;
- }
- }
-
- private void ungetServletContext(@Nonnull final ContextInfo contextInfo)
- {
- final Long key = contextInfo.getServiceId();
- synchronized ( this.contextMap )
- {
- ContextHolder holder = this.contextMap.get(key);
- if ( holder != null )
- {
- holder.counter--;
- if ( holder.counter <= 0 )
- {
- this.contextMap.remove(key);
- }
- }
- }
- }
-
- /**
- * Register a servlet.
- * @param contextInfo The servlet context helper info
- * @param servletInfo The servlet info
- */
- public void registerServlet(@Nonnull final ContextInfo contextInfo,
- @Nonnull final ServletInfo servletInfo)
- {
- final Servlet servlet = this.bundleContext.getServiceObjects(servletInfo.getServiceReference()).getService();
- // TODO create failure DTO if null
- if ( servlet != null )
- {
- final ServletHandler handler = new ServletHandler(contextInfo,
- getServletContext(contextInfo, servletInfo),
- servletInfo,
- servlet);
- try {
- this.handlerRegistry.addServlet(contextInfo, handler);
- } catch (ServletException e) {
- // TODO create failure DTO
- } catch (NamespaceException e) {
- // TODO create failure DTO
- }
- }
- }
-
- /**
- * Unregister a servlet
- * @param contextInfo The servlet context helper info
- * @param servletInfo The servlet info
- */
- public void unregisterServlet(@Nonnull final ContextInfo contextInfo, @Nonnull final ServletInfo servletInfo)
- {
- final Servlet instance = this.handlerRegistry.removeServlet(contextInfo, servletInfo, true);
- if ( instance != null )
- {
- this.bundleContext.getServiceObjects(servletInfo.getServiceReference()).ungetService(instance);
- this.ungetServletContext(contextInfo);
- }
- }
-
- /**
- * Register a filter
- * @param contextInfo The servlet context helper info
- * @param filterInfo The filter info
- */
- public void registerFilter(@Nonnull final ContextInfo contextInfo,
- @Nonnull final FilterInfo filterInfo)
- {
- final Filter filter = this.bundleContext.getServiceObjects(filterInfo.getServiceReference()).getService();
- // TODO create failure DTO if null
- if ( filter != null )
- {
- final FilterHandler handler = new FilterHandler(contextInfo,
- getServletContext(contextInfo, filterInfo),
- filter,
- filterInfo);
- try {
- this.handlerRegistry.addFilter(handler);
- } catch (final ServletException e) {
- // TODO create failure DTO
- }
- }
- }
-
- /**
- * Unregister a filter
- * @param contextInfo The servlet context helper info
- * @param filterInfo The filter info
- */
- public void unregisterFilter(@Nonnull final ContextInfo contextInfo, @Nonnull final FilterInfo filterInfo)
- {
- final Filter instance = this.handlerRegistry.removeFilter(filterInfo, true);
- if ( instance != null )
- {
- this.bundleContext.getServiceObjects(filterInfo.getServiceReference()).ungetService(instance);
- this.ungetServletContext(contextInfo);
- }
- }
-
- /**
- * Register a resource.
- * @param contextInfo The servlet context helper info
- * @param resourceInfo The resource info
- */
- public void registerResource(@Nonnull final ContextInfo contextInfo,
- @Nonnull final ResourceInfo resourceInfo)
- {
- final ServletInfo servletInfo = new ServletInfo(resourceInfo, new ResourceServlet(resourceInfo.getPrefix()));
-
- this.registerServlet(contextInfo, servletInfo);
- }
-
- /**
- * Unregister a resource.
- * @param contextInfo The servlet context helper info
- * @param resourceInfo The resource info
- */
- public void unregisterResource(@Nonnull final ContextInfo contextInfo, @Nonnull final ResourceInfo resourceInfo)
- {
- final ServletInfo servletInfo = new ServletInfo(resourceInfo, null);
- this.unregisterServlet(contextInfo, servletInfo);
- }
-}
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
new file mode 100644
index 0000000..d9afe6e
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ContextHandler.java
@@ -0,0 +1,154 @@
+/*
+ * 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.Nonnull;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+import org.apache.felix.http.base.internal.context.ExtServletContext;
+import org.apache.felix.http.base.internal.runtime.ContextInfo;
+import org.apache.felix.http.base.internal.runtime.ServletContextListenerInfo;
+import org.osgi.framework.Bundle;
+import org.osgi.service.http.context.ServletContextHelper;
+
+public final class ContextHandler implements Comparable<ContextHandler>
+{
+ /** The info object for the context. */
+ private final ContextInfo info;
+
+ /** A map of all created servlet contexts. */
+ private final Map<Long, ContextHolder> contextMap = new HashMap<Long, ContextHolder>();
+
+ /** The shared part of the servlet context. */
+ private final ServletContext sharedContext;
+
+ private final Map<Long, ServletContextListener> listeners = new HashMap<Long, ServletContextListener>();
+
+ /**
+ * Create new handler.
+ * @param info
+ * @param webContext
+ */
+ public ContextHandler(final ContextInfo info, final ServletContext webContext)
+ {
+ this.info = info;
+ this.sharedContext = new SharedServletContextImpl(webContext);
+ }
+
+ /**
+ * Get the context info
+ */
+ public ContextInfo getContextInfo()
+ {
+ return this.info;
+ }
+
+ @Override
+ public int compareTo(final ContextHandler o)
+ {
+ // TODO Auto-generated method stub
+ return this.info.compareTo(o.info);
+ }
+
+ public void activate(final Bundle bundle)
+ {
+ getServletContext(bundle);
+ }
+
+ public void deactivate(final Bundle bundle)
+ {
+ this.ungetServletContext(bundle);
+ }
+
+ public void initialized(final Bundle bundle, final ServletContextListenerInfo listenerInfo)
+ {
+ final ServletContextListener listener = bundle.getBundleContext().getServiceObjects(listenerInfo.getServiceReference()).getService();
+ if ( listener != null)
+ {
+ // no need to sync map - initialized is called in sync
+ this.listeners.put(listenerInfo.getServiceId(), listener);
+
+ final ServletContext context = this.getServletContext(listenerInfo.getServiceReference().getBundle());
+
+ listener.contextInitialized(new ServletContextEvent(context));
+ }
+ }
+
+ public void destroyed(final ServletContextListenerInfo listenerInfo)
+ {
+ // no need to sync map - destroyed is called in sync
+ final ServletContextListener listener = this.listeners.remove(listenerInfo.getServiceId());
+ if ( listener != null )
+ {
+ final ServletContext context = this.getServletContext(listenerInfo.getServiceReference().getBundle());
+ listener.contextDestroyed(new ServletContextEvent(context));
+ this.ungetServletContext(listenerInfo.getServiceReference().getBundle());
+ }
+ }
+
+ public ExtServletContext getServletContext(@Nonnull final Bundle bundle)
+ {
+ final Long key = bundle.getBundleId();
+ synchronized ( this.contextMap )
+ {
+ ContextHolder holder = this.contextMap.get(key);
+ if ( holder == null )
+ {
+ holder = new ContextHolder();
+ // TODO check for null
+ holder.servletContextHelper = bundle.getBundleContext().getServiceObjects(this.info.getServiceReference()).getService();
+ holder.servletContext = new PerBundleServletContextImpl(bundle,
+ this.sharedContext,
+ holder.servletContextHelper);
+ }
+ holder.counter++;
+
+ return holder.servletContext;
+ }
+ }
+
+ public void ungetServletContext(@Nonnull final Bundle bundle)
+ {
+ final Long key = bundle.getBundleId();
+ synchronized ( this.contextMap )
+ {
+ ContextHolder holder = this.contextMap.get(key);
+ if ( holder != null )
+ {
+ holder.counter--;
+ if ( holder.counter <= 0 )
+ {
+ this.contextMap.remove(key);
+ bundle.getBundleContext().getServiceObjects(this.info.getServiceReference()).ungetService(holder.servletContextHelper);
+ }
+ }
+ }
+ }
+
+ private static final class ContextHolder
+ {
+ public long counter;
+ public ExtServletContext servletContext;
+ public ServletContextHelper servletContextHelper;
+ }
+
+}
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
deleted file mode 100644
index f16d141..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ExtenderManager.java
+++ /dev/null
@@ -1,62 +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.ArrayList;
-
-import org.apache.felix.http.base.internal.service.InternalHttpService;
-import org.apache.felix.http.base.internal.whiteboard.tracker.FilterTracker;
-import org.apache.felix.http.base.internal.whiteboard.tracker.ResourceTracker;
-import org.apache.felix.http.base.internal.whiteboard.tracker.ServletContextHelperTracker;
-import org.apache.felix.http.base.internal.whiteboard.tracker.ServletTracker;
-import org.osgi.framework.BundleContext;
-import org.osgi.util.tracker.ServiceTracker;
-
-/**
- * TODO - move code to ServletContextHelperManager
- */
-public final class ExtenderManager
-{
- private final ServletContextHelperManager contextManager;
-
- private final ArrayList<ServiceTracker<?, ?>> trackers = new ArrayList<ServiceTracker<?, ?>>();
-
- public ExtenderManager(final InternalHttpService httpService, final BundleContext bundleContext)
- {
- this.contextManager = new ServletContextHelperManager(bundleContext, httpService);
- addTracker(new FilterTracker(bundleContext, contextManager));
- addTracker(new ServletTracker(bundleContext, this.contextManager));
- addTracker(new ResourceTracker(bundleContext, this.contextManager));
- addTracker(new ServletContextHelperTracker(bundleContext, this.contextManager));
- }
-
- public void close()
- {
- for(final ServiceTracker<?, ?> t : this.trackers)
- {
- t.close();
- }
- this.trackers.clear();
- this.contextManager.close();
- }
-
- private void addTracker(ServiceTracker<?, ?> tracker)
- {
- this.trackers.add(tracker);
- tracker.open();
- }
- }
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/HttpContextBridge.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/HttpContextBridge.java
deleted file mode 100644
index f4bb94c..0000000
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/HttpContextBridge.java
+++ /dev/null
@@ -1,71 +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 org.osgi.service.http.HttpContext;
-import org.osgi.service.http.context.ServletContextHelper;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-import java.net.URL;
-import java.util.Set;
-
-public class HttpContextBridge extends ServletContextHelper implements HttpContext {
-
- private final ServletContextHelper delegatee;
-
- public HttpContextBridge(final ServletContextHelper delegatee)
- {
- this.delegatee = delegatee;
- }
-
- @Override
- public boolean handleSecurity(HttpServletRequest request, HttpServletResponse response) throws IOException
- {
- return delegatee.handleSecurity(request, response);
- }
-
- @Override
- public URL getResource(String name)
- {
- return delegatee.getResource(name);
- }
-
- @Override
- public String getMimeType(String name)
- {
- return delegatee.getMimeType(name);
- }
-
- @Override
- public Set<String> getResourcePaths(String path)
- {
- return delegatee.getResourcePaths(path);
- }
-
- @Override
- public String getRealPath(String path)
- {
- return delegatee.getRealPath(path);
- }
-
- public ServletContextHelper getDelegatee()
- {
- return delegatee;
- }
-}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/PerBundleServletContextImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/PerBundleServletContextImpl.java
new file mode 100644
index 0000000..3fae532
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/PerBundleServletContextImpl.java
@@ -0,0 +1,399 @@
+/*
+ * 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.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.EventListener;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterRegistration;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.Servlet;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRegistration;
+import javax.servlet.ServletRegistration.Dynamic;
+import javax.servlet.SessionCookieConfig;
+import javax.servlet.SessionTrackingMode;
+import javax.servlet.descriptor.JspConfigDescriptor;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.felix.http.base.internal.context.ExtServletContext;
+import org.osgi.framework.Bundle;
+import org.osgi.service.http.context.ServletContextHelper;
+
+/**
+ * This servlet context implementation represents the per
+ * bundle specific part of a servlet context backed by a
+ * servlet context helper.
+ *
+ */
+public class PerBundleServletContextImpl implements ExtServletContext {
+
+ private final Bundle bundle;
+ private final ServletContext delegatee;
+ private final ServletContextHelper contextHelper;
+
+ public PerBundleServletContextImpl(final Bundle bundle,
+ final ServletContext sharedContext,
+ final ServletContextHelper delegatee)
+ {
+ this.bundle = bundle;
+ this.delegatee = sharedContext;
+ this.contextHelper = delegatee;
+ }
+
+ @Override
+ public boolean handleSecurity(final HttpServletRequest req,
+ final HttpServletResponse res)
+ throws IOException
+ {
+ return this.contextHelper.handleSecurity(req, res);
+ }
+
+ @Override
+ public ClassLoader getClassLoader()
+ {
+ return this.bundle.getClass().getClassLoader();
+ }
+
+ /**
+ * @see javax.servlet.ServletContext#getResource(java.lang.String)
+ */
+ @Override
+ public URL getResource(final String path)
+ {
+ // is implemented by {@link PerBundleServletContextImpl}.
+ return this.contextHelper.getResource(path);
+ }
+
+ @Override
+ public String getMimeType(final String name)
+ {
+ // is implemented by {@link PerBundleServletContextImpl}.
+ return this.contextHelper.getMimeType(name);
+ }
+
+ @Override
+ public String getRealPath(final String path)
+ {
+ // is implemented by {@link PerBundleServletContextImpl}.
+ return this.contextHelper.getRealPath(path);
+ }
+
+ @Override
+ public Set<String> getResourcePaths(final String path)
+ {
+ return this.contextHelper.getResourcePaths(path);
+ }
+
+ @Override
+ public String getContextPath()
+ {
+ return delegatee.getContextPath();
+ }
+
+ @Override
+ public ServletContext getContext(String uripath)
+ {
+ return delegatee.getContext(uripath);
+ }
+
+ @Override
+ public int getMajorVersion()
+ {
+ return delegatee.getMajorVersion();
+ }
+
+ @Override
+ public int getMinorVersion()
+ {
+ return delegatee.getMinorVersion();
+ }
+
+ @Override
+ public int getEffectiveMajorVersion()
+ {
+ return delegatee.getEffectiveMajorVersion();
+ }
+
+ @Override
+ public int getEffectiveMinorVersion()
+ {
+ return delegatee.getEffectiveMinorVersion();
+ }
+
+ @Override
+ public InputStream getResourceAsStream(String path)
+ {
+ return delegatee.getResourceAsStream(path);
+ }
+
+ @Override
+ public RequestDispatcher getRequestDispatcher(String path)
+ {
+ return delegatee.getRequestDispatcher(path);
+ }
+
+ @Override
+ public RequestDispatcher getNamedDispatcher(String name)
+ {
+ return delegatee.getNamedDispatcher(name);
+ }
+
+ @Override
+ public Servlet getServlet(String name) throws ServletException
+ {
+ return delegatee.getServlet(name);
+ }
+
+ @Override
+ public Enumeration<Servlet> getServlets()
+ {
+ return delegatee.getServlets();
+ }
+
+ @Override
+ public Enumeration<String> getServletNames()
+ {
+ return delegatee.getServletNames();
+ }
+
+ @Override
+ public void log(String msg)
+ {
+ delegatee.log(msg);
+ }
+
+ @Override
+ public void log(Exception exception, String msg)
+ {
+ delegatee.log(exception, msg);
+ }
+
+ @Override
+ public void log(String message, Throwable throwable)
+ {
+ delegatee.log(message, throwable);
+ }
+
+ @Override
+ public String getServerInfo()
+ {
+ return delegatee.getServerInfo();
+ }
+
+ @Override
+ public String getInitParameter(String name)
+ {
+ return delegatee.getInitParameter(name);
+ }
+
+ @Override
+ public Enumeration<String> getInitParameterNames()
+ {
+ return delegatee.getInitParameterNames();
+ }
+
+ @Override
+ public boolean setInitParameter(String name, String value)
+ {
+ return delegatee.setInitParameter(name, value);
+ }
+
+ @Override
+ public Object getAttribute(String name)
+ {
+ return delegatee.getAttribute(name);
+ }
+
+ @Override
+ public Enumeration<String> getAttributeNames()
+ {
+ return delegatee.getAttributeNames();
+ }
+
+ @Override
+ public void setAttribute(String name, Object object)
+ {
+ delegatee.setAttribute(name, object);
+ }
+
+ @Override
+ public void removeAttribute(String name)
+ {
+ delegatee.removeAttribute(name);
+ }
+
+ @Override
+ public String getServletContextName()
+ {
+ return delegatee.getServletContextName();
+ }
+
+ @Override
+ public Dynamic addServlet(String servletName, String className)
+ {
+ return delegatee.addServlet(servletName, className);
+ }
+
+ @Override
+ public Dynamic addServlet(String servletName, Servlet servlet)
+ {
+ return delegatee.addServlet(servletName, servlet);
+ }
+
+ @Override
+ public Dynamic addServlet(String servletName,
+ Class<? extends Servlet> servletClass)
+ {
+ return delegatee.addServlet(servletName, servletClass);
+ }
+
+ @Override
+ public <T extends Servlet> T createServlet(Class<T> clazz)
+ throws ServletException
+ {
+ return delegatee.createServlet(clazz);
+ }
+
+ @Override
+ public ServletRegistration getServletRegistration(String servletName)
+ {
+ return delegatee.getServletRegistration(servletName);
+ }
+
+ @Override
+ public Map<String, ? extends ServletRegistration> getServletRegistrations()
+ {
+ return delegatee.getServletRegistrations();
+ }
+
+ @Override
+ public javax.servlet.FilterRegistration.Dynamic addFilter(
+ String filterName, String className)
+ {
+ return delegatee.addFilter(filterName, className);
+ }
+
+ @Override
+ public javax.servlet.FilterRegistration.Dynamic addFilter(
+ String filterName, Filter filter)
+ {
+ return delegatee.addFilter(filterName, filter);
+ }
+
+ @Override
+ public javax.servlet.FilterRegistration.Dynamic addFilter(
+ String filterName, Class<? extends Filter> filterClass)
+ {
+ return delegatee.addFilter(filterName, filterClass);
+ }
+
+ @Override
+ public <T extends Filter> T createFilter(Class<T> clazz)
+ throws ServletException
+ {
+ return delegatee.createFilter(clazz);
+ }
+
+ @Override
+ public FilterRegistration getFilterRegistration(String filterName)
+ {
+ return delegatee.getFilterRegistration(filterName);
+ }
+
+ @Override
+ public Map<String, ? extends FilterRegistration> getFilterRegistrations()
+ {
+ return delegatee.getFilterRegistrations();
+ }
+
+ @Override
+ public SessionCookieConfig getSessionCookieConfig()
+ {
+ return delegatee.getSessionCookieConfig();
+ }
+
+ @Override
+ public void setSessionTrackingModes(
+ Set<SessionTrackingMode> sessionTrackingModes)
+ {
+ delegatee.setSessionTrackingModes(sessionTrackingModes);
+ }
+
+ @Override
+ public Set<SessionTrackingMode> getDefaultSessionTrackingModes()
+ {
+ return delegatee.getDefaultSessionTrackingModes();
+ }
+
+ @Override
+ public Set<SessionTrackingMode> getEffectiveSessionTrackingModes()
+ {
+ return delegatee.getEffectiveSessionTrackingModes();
+ }
+
+ @Override
+ public void addListener(String className)
+ {
+ delegatee.addListener(className);
+ }
+
+ @Override
+ public <T extends EventListener> void addListener(T t)
+ {
+ delegatee.addListener(t);
+ }
+
+ @Override
+ public void addListener(Class<? extends EventListener> listenerClass)
+ {
+ delegatee.addListener(listenerClass);
+ }
+
+ @Override
+ public <T extends EventListener> T createListener(Class<T> clazz)
+ throws ServletException
+ {
+ return delegatee.createListener(clazz);
+ }
+
+ @Override
+ public JspConfigDescriptor getJspConfigDescriptor()
+ {
+ return delegatee.getJspConfigDescriptor();
+ }
+
+ @Override
+ public void declareRoles(String... roleNames)
+ {
+ delegatee.declareRoles(roleNames);
+ }
+
+ @Override
+ public String getVirtualServerName()
+ {
+ return delegatee.getVirtualServerName();
+ }
+}
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 ec4a8e8..41c2b0a 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
@@ -25,12 +25,14 @@
import java.util.List;
import java.util.Map;
+import javax.servlet.ServletContext;
+
import org.apache.felix.http.base.internal.runtime.ContextInfo;
import org.apache.felix.http.base.internal.runtime.FilterInfo;
import org.apache.felix.http.base.internal.runtime.ResourceInfo;
+import org.apache.felix.http.base.internal.runtime.ServletContextListenerInfo;
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.InternalHttpService;
import org.apache.felix.http.base.internal.util.MimeTypes;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@@ -43,22 +45,28 @@
public final class ServletContextHelperManager
{
/** A map containing all servlet context registrations. Mapped by context name */
- private final Map<String, List<ContextInfo>> contextMap = new HashMap<String, List<ContextInfo>>();
+ private final Map<String, List<ContextHandler>> contextMap = new HashMap<String, List<ContextHandler>>();
/** A map with all servlet/filter registrations, mapped by abstract info. */
- private final Map<WhiteboardServiceInfo<?>, List<ContextInfo>> servicesMap = new HashMap<WhiteboardServiceInfo<?>, List<ContextInfo>>();
+ private final Map<WhiteboardServiceInfo<?>, List<ContextHandler>> servicesMap = new HashMap<WhiteboardServiceInfo<?>, List<ContextHandler>>();
- private final InternalHttpService httpService;
+ private final WhiteboardHttpService httpService;
private final ServiceRegistration<ServletContextHelper> defaultContextRegistration;
+ private final ServletContext webContext;
+
+ private final Bundle bundle;
+
/**
* Create a new servlet context helper manager
* and the default context
*/
- public ServletContextHelperManager(final BundleContext bundleContext, final InternalHttpService httpService)
+ public ServletContextHelperManager(final BundleContext bundleContext, final ServletContext webContext, final WhiteboardHttpService httpService)
{
this.httpService = httpService;
+ this.webContext = webContext;
+ this.bundle = bundleContext.getBundle();
final Dictionary<String, Object> props = new Hashtable<String, Object>();
props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, HttpWhiteboardConstants.HTTP_WHITEBOARD_DEFAULT_CONTEXT_NAME);
@@ -92,6 +100,9 @@
props);
}
+ /**
+ * Clean up the instance
+ */
public void close()
{
// TODO cleanup
@@ -99,32 +110,69 @@
this.defaultContextRegistration.unregister();
}
- private void activate(final ContextInfo contextInfo)
+ /**
+ * Activate a servlet context helper.
+ * @param contextInfo A context info
+ */
+ private void activate(final ContextHandler handler)
{
- for(final Map.Entry<WhiteboardServiceInfo<?>, List<ContextInfo>> entry : this.servicesMap.entrySet())
+ handler.activate(this.bundle);
+ // context listeners first
+ final List<WhiteboardServiceInfo<?>> services = new ArrayList<WhiteboardServiceInfo<?>>();
+ for(final Map.Entry<WhiteboardServiceInfo<?>, List<ContextHandler>> entry : this.servicesMap.entrySet())
{
- if ( entry.getKey().getContextSelectionFilter().match(contextInfo.getServiceReference()) )
+ if ( entry.getKey().getContextSelectionFilter().match(handler.getContextInfo().getServiceReference()) )
{
- entry.getValue().add(contextInfo);
- this.registerWhiteboardService(contextInfo, entry.getKey());
+ entry.getValue().add(handler);
+ if ( entry.getKey() instanceof ServletContextListenerInfo )
+ {
+ handler.initialized(this.bundle, (ServletContextListenerInfo)entry.getKey());
+ }
+ else
+ {
+ services.add(entry.getKey());
+ }
}
}
+ // now register services
+ for(final WhiteboardServiceInfo<?> info : services)
+ {
+ this.registerWhiteboardService(handler, info);
+ }
}
- private void deactivate(final ContextInfo contextInfo)
+ /**
+ * Deactivate a servlet context helper.
+ * @param contextInfo A context info
+ */
+ private void deactivate(final ContextHandler handler)
{
- final Iterator<Map.Entry<WhiteboardServiceInfo<?>, List<ContextInfo>>> i = this.servicesMap.entrySet().iterator();
+ // context listeners last
+ final List<ServletContextListenerInfo> listeners = new ArrayList<ServletContextListenerInfo>();
+ final Iterator<Map.Entry<WhiteboardServiceInfo<?>, List<ContextHandler>>> i = this.servicesMap.entrySet().iterator();
while ( i.hasNext() )
{
- final Map.Entry<WhiteboardServiceInfo<?>, List<ContextInfo>> entry = i.next();
- if ( entry.getValue().remove(contextInfo) )
+ final Map.Entry<WhiteboardServiceInfo<?>, List<ContextHandler>> entry = i.next();
+ if ( entry.getValue().remove(handler) )
{
- this.unregisterWhiteboardService(contextInfo, entry.getKey());
+ if ( entry.getKey() instanceof ServletContextListenerInfo )
+ {
+ listeners.add((ServletContextListenerInfo)entry.getKey());
+ }
+ else
+ {
+ this.unregisterWhiteboardService(handler, entry.getKey());
+ }
if ( entry.getValue().isEmpty() ) {
i.remove();
}
}
}
+ for(final ServletContextListenerInfo info : listeners)
+ {
+ handler.destroyed(info);
+ }
+ handler.deactivate(this.bundle);
}
/**
@@ -132,25 +180,26 @@
*/
public void addContextHelper(final ContextInfo info)
{
+ final ContextHandler handler = new ContextHandler(info, this.webContext);
synchronized ( this.contextMap )
{
- List<ContextInfo> holderList = this.contextMap.get(info.getName());
- if ( holderList == null )
+ List<ContextHandler> handlerList = this.contextMap.get(info.getName());
+ if ( handlerList == null )
{
- holderList = new ArrayList<ContextInfo>();
- this.contextMap.put(info.getName(), holderList);
+ handlerList = new ArrayList<ContextHandler>();
+ this.contextMap.put(info.getName(), handlerList);
}
- holderList.add(info);
- Collections.sort(holderList);
+ handlerList.add(handler);
+ Collections.sort(handlerList);
// check for activate/deactivate
- if ( holderList.get(0) == info )
+ if ( handlerList.get(0) == handler )
{
// check for deactivate
- if ( holderList.size() > 1 )
+ if ( handlerList.size() > 1 )
{
- this.deactivate(holderList.get(1));
+ this.deactivate(handlerList.get(1));
}
- this.activate(info);
+ this.activate(handler);
}
}
}
@@ -162,46 +211,49 @@
{
synchronized ( this.contextMap )
{
- final List<ContextInfo> holderList = this.contextMap.get(info.getName());
- if ( holderList != null )
+ final List<ContextHandler> handlerList = this.contextMap.get(info.getName());
+ if ( handlerList != null )
{
- final Iterator<ContextInfo> i = holderList.iterator();
+ final Iterator<ContextHandler> i = handlerList.iterator();
boolean first = true;
boolean activateNext = false;
while ( i.hasNext() )
{
- final ContextInfo holder = i.next();
- if ( holder.compareTo(info) == 0 )
+ final ContextHandler handler = i.next();
+ if ( handler.getContextInfo().compareTo(info) == 0 )
{
i.remove();
// check for deactivate
if ( first )
{
- this.deactivate(holder);
+ this.deactivate(handler);
activateNext = true;
}
break;
}
first = false;
}
- if ( holderList.isEmpty() )
+ if ( handlerList.isEmpty() )
{
this.contextMap.remove(info.getName());
}
else if ( activateNext )
{
- this.activate(holderList.get(0));
+ this.activate(handlerList.get(0));
}
}
}
}
- private List<ContextInfo> getMatchingContexts(final WhiteboardServiceInfo<?> info)
+ /**
+ * Find the list of matching contexts for the whiteboard service
+ */
+ private List<ContextHandler> getMatchingContexts(final WhiteboardServiceInfo<?> info)
{
- final List<ContextInfo> result = new ArrayList<ContextInfo>();
- for(final List<ContextInfo> holders : this.contextMap.values()) {
- final ContextInfo h = holders.get(0);
- if ( info.getContextSelectionFilter().match(h.getServiceReference()) )
+ final List<ContextHandler> result = new ArrayList<ContextHandler>();
+ for(final List<ContextHandler> handlerList : this.contextMap.values()) {
+ final ContextHandler h = handlerList.get(0);
+ if ( info.getContextSelectionFilter().match(h.getContextInfo().getServiceReference()) )
{
result.add(h);
}
@@ -217,9 +269,9 @@
{
synchronized ( this.contextMap )
{
- final List<ContextInfo> holderList = this.getMatchingContexts(info);
- this.servicesMap.put(info, holderList);
- for(final ContextInfo h : holderList)
+ final List<ContextHandler> handlerList = this.getMatchingContexts(info);
+ this.servicesMap.put(info, handlerList);
+ for(final ContextHandler h : handlerList)
{
this.registerWhiteboardService(h, info);
}
@@ -234,10 +286,10 @@
{
synchronized ( this.contextMap )
{
- final List<ContextInfo> holderList = this.servicesMap.remove(info);
- if ( holderList != null )
+ final List<ContextHandler> handlerList = this.servicesMap.remove(info);
+ if ( handlerList != null )
{
- for(final ContextInfo h : holderList)
+ for(final ContextHandler h : handlerList)
{
this.unregisterWhiteboardService(h, info);
}
@@ -250,19 +302,19 @@
* @param contextInfo Context info
* @param info Whiteboard service info
*/
- private void registerWhiteboardService(final ContextInfo contextInfo, final WhiteboardServiceInfo<?> info)
+ private void registerWhiteboardService(final ContextHandler handler, final WhiteboardServiceInfo<?> info)
{
if ( info instanceof ServletInfo )
{
- this.httpService.registerServlet(contextInfo, (ServletInfo)info);
+ this.httpService.registerServlet(handler, (ServletInfo)info);
}
else if ( info instanceof FilterInfo )
{
- this.httpService.registerFilter(contextInfo, (FilterInfo)info);
+ this.httpService.registerFilter(handler, (FilterInfo)info);
}
else if ( info instanceof ResourceInfo )
{
- this.httpService.registerResource(contextInfo, (ResourceInfo)info);
+ this.httpService.registerResource(handler, (ResourceInfo)info);
}
}
@@ -271,19 +323,19 @@
* @param contextInfo Context info
* @param info Whiteboard service info
*/
- private void unregisterWhiteboardService(final ContextInfo contextInfo, final WhiteboardServiceInfo<?> info)
+ private void unregisterWhiteboardService(final ContextHandler handler, final WhiteboardServiceInfo<?> info)
{
if ( info instanceof ServletInfo )
{
- this.httpService.unregisterServlet(contextInfo, (ServletInfo)info);
+ this.httpService.unregisterServlet(handler, (ServletInfo)info);
}
else if ( info instanceof FilterInfo )
{
- this.httpService.unregisterFilter(contextInfo, (FilterInfo)info);
+ this.httpService.unregisterFilter(handler, (FilterInfo)info);
}
else if ( info instanceof ResourceInfo )
{
- this.httpService.unregisterResource(contextInfo, (ResourceInfo)info);
+ this.httpService.unregisterResource(handler, (ResourceInfo)info);
}
}
}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/service/ServletContextImpl.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/SharedServletContextImpl.java
similarity index 86%
rename from http/base/src/main/java/org/apache/felix/http/base/internal/service/ServletContextImpl.java
rename to http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/SharedServletContextImpl.java
index d177dbb..aa34c86 100644
--- a/http/base/src/main/java/org/apache/felix/http/base/internal/service/ServletContextImpl.java
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/SharedServletContextImpl.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.felix.http.base.internal.service;
+package org.apache.felix.http.base.internal.whiteboard;
import java.io.IOException;
import java.io.InputStream;
@@ -36,39 +36,31 @@
import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode;
import javax.servlet.descriptor.JspConfigDescriptor;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.apache.felix.http.base.internal.context.ExtServletContext;
import org.apache.felix.http.base.internal.logger.SystemLogger;
-import org.osgi.framework.Bundle;
-import org.osgi.service.http.context.ServletContextHelper;
-public class ServletContextImpl implements ExtServletContext {
+/**
+ * This servlet context implementation represents the shared
+ * part for a servlet context backed by a servlet context helper.
+ *
+ * For each using bundle, a {@link PerBundleServletContextImpl} is created.
+ */
+public class SharedServletContextImpl implements ServletContext
+{
- private final ServletContextHelper delegatee;
-
- private final Bundle bundle;
private final ServletContext context;
- private final Map<String, Object> attributes;
+ private final Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();
- public ServletContextImpl(final Bundle bundle,
- final ServletContext context,
- final ServletContextHelper delegatee)
+ public SharedServletContextImpl(final ServletContext webContext)
{
- this.bundle = bundle;
- this.context = context;
- this.delegatee = delegatee;
- this.attributes = new ConcurrentHashMap<String, Object>();
+ this.context = webContext;
}
- /**
- * @see org.apache.felix.http.base.internal.context.ExtServletContext#handleSecurity(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
- */
@Override
- public boolean handleSecurity(HttpServletRequest request, HttpServletResponse response) throws IOException
+ public ClassLoader getClassLoader()
{
- return delegatee.handleSecurity(request, response);
+ // is implemented by {@link PerBundleServletContextImpl}.
+ return null;
}
/**
@@ -77,13 +69,29 @@
@Override
public URL getResource(String path)
{
- return delegatee.getResource(path);
+ // is implemented by {@link PerBundleServletContextImpl}.
+ return null;
}
@Override
public String getMimeType(String file)
{
- return delegatee.getMimeType(file);
+ // is implemented by {@link PerBundleServletContextImpl}.
+ return null;
+ }
+
+ @Override
+ public String getRealPath(String path)
+ {
+ // is implemented by {@link PerBundleServletContextImpl}.
+ return null;
+ }
+
+ @Override
+ public Set<String> getResourcePaths(final String path)
+ {
+ // is implemented by {@link PerBundleServletContextImpl}.
+ return null;
}
@Override
@@ -182,12 +190,6 @@
}
@Override
- public ClassLoader getClassLoader()
- {
- return bundle.getClass().getClassLoader();
- }
-
- @Override
public ServletContext getContext(String uri)
{
// TODO
@@ -274,12 +276,6 @@
}
@Override
- public String getRealPath(String path)
- {
- return this.delegatee.getRealPath(path);
- }
-
- @Override
public RequestDispatcher getRequestDispatcher(String uri)
{
return this.context.getRequestDispatcher(uri);
@@ -304,12 +300,6 @@
}
@Override
- public Set<String> getResourcePaths(final String path)
- {
- return this.delegatee.getResourcePaths(path);
- }
-
- @Override
public String getServerInfo()
{
return this.context.getServerInfo();
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
new file mode 100644
index 0000000..db46053
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardHttpService.java
@@ -0,0 +1,193 @@
+/*
+ * 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.ArrayList;
+
+import javax.annotation.Nonnull;
+import javax.servlet.Filter;
+import javax.servlet.Servlet;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+
+import org.apache.felix.http.base.internal.handler.FilterHandler;
+import org.apache.felix.http.base.internal.handler.HandlerRegistry;
+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.ResourceInfo;
+import org.apache.felix.http.base.internal.runtime.ServletInfo;
+import org.apache.felix.http.base.internal.service.ResourceServlet;
+import org.apache.felix.http.base.internal.whiteboard.tracker.FilterTracker;
+import org.apache.felix.http.base.internal.whiteboard.tracker.ResourceTracker;
+import org.apache.felix.http.base.internal.whiteboard.tracker.ServletContextHelperTracker;
+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.util.tracker.ServiceTracker;
+
+public final class WhiteboardHttpService
+{
+
+ private final HandlerRegistry handlerRegistry;
+
+ private final BundleContext bundleContext;
+
+ private final ServletContextHelperManager contextManager;
+
+ private final ArrayList<ServiceTracker<?, ?>> trackers = new ArrayList<ServiceTracker<?, ?>>();
+
+ /**
+ * Create a new whiteboard http service
+ * @param bundleContext
+ * @param context
+ * @param handlerRegistry
+ */
+ public WhiteboardHttpService(final BundleContext bundleContext,
+ final ServletContext context,
+ final HandlerRegistry handlerRegistry)
+ {
+ this.handlerRegistry = handlerRegistry;
+ this.bundleContext = bundleContext;
+ this.contextManager = new ServletContextHelperManager(bundleContext, context, this);
+ addTracker(new FilterTracker(bundleContext, contextManager));
+ addTracker(new ServletTracker(bundleContext, this.contextManager));
+ addTracker(new ResourceTracker(bundleContext, this.contextManager));
+ addTracker(new ServletContextHelperTracker(bundleContext, this.contextManager));
+ addTracker(new ServletContextListenerTracker(bundleContext, this.contextManager));
+ }
+
+ public void close()
+ {
+ for(final ServiceTracker<?, ?> t : this.trackers)
+ {
+ t.close();
+ }
+ this.trackers.clear();
+ this.contextManager.close();
+ }
+
+ private void addTracker(ServiceTracker<?, ?> tracker)
+ {
+ this.trackers.add(tracker);
+ tracker.open();
+ }
+
+ /**
+ * Register a servlet.
+ * @param contextInfo The servlet context helper info
+ * @param servletInfo The servlet info
+ */
+ 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 ServletHandler handler = new ServletHandler(contextHandler.getContextInfo(),
+ contextHandler.getServletContext(servletInfo.getServiceReference().getBundle()),
+ servletInfo,
+ servlet);
+ try {
+ this.handlerRegistry.addServlet(contextHandler.getContextInfo(), handler);
+ } catch (ServletException e) {
+ // TODO create failure DTO
+ } catch (NamespaceException e) {
+ // TODO create failure DTO
+ }
+ }
+ }
+
+ /**
+ * Unregister a servlet
+ * @param contextInfo The servlet context helper info
+ * @param servletInfo The servlet info
+ */
+ public void unregisterServlet(@Nonnull final ContextHandler contextHandler, @Nonnull final ServletInfo servletInfo)
+ {
+ final Servlet instance = this.handlerRegistry.removeServlet(contextHandler.getContextInfo(), servletInfo, true);
+ if ( instance != null )
+ {
+ this.bundleContext.getServiceObjects(servletInfo.getServiceReference()).ungetService(instance);
+ contextHandler.ungetServletContext(servletInfo.getServiceReference().getBundle());
+ }
+ }
+
+ /**
+ * Register a filter
+ * @param contextInfo The servlet context helper info
+ * @param filterInfo The filter info
+ */
+ public void registerFilter(@Nonnull final ContextHandler contextHandler,
+ @Nonnull final FilterInfo filterInfo)
+ {
+ final Filter filter = this.bundleContext.getServiceObjects(filterInfo.getServiceReference()).getService();
+ // TODO create failure DTO if null
+ if ( filter != null )
+ {
+ final FilterHandler handler = new FilterHandler(contextHandler.getContextInfo(),
+ contextHandler.getServletContext(filterInfo.getServiceReference().getBundle()),
+ filter,
+ filterInfo);
+ try {
+ this.handlerRegistry.addFilter(handler);
+ } catch (final ServletException e) {
+ // TODO create failure DTO
+ }
+ }
+ }
+
+ /**
+ * Unregister a filter
+ * @param contextInfo The servlet context helper info
+ * @param filterInfo The filter info
+ */
+ public void unregisterFilter(@Nonnull final ContextHandler contextHandler, @Nonnull final FilterInfo filterInfo)
+ {
+ final Filter instance = this.handlerRegistry.removeFilter(filterInfo, true);
+ if ( instance != null )
+ {
+ this.bundleContext.getServiceObjects(filterInfo.getServiceReference()).ungetService(instance);
+ contextHandler.ungetServletContext(filterInfo.getServiceReference().getBundle());
+ }
+ }
+
+ /**
+ * Register a resource.
+ * @param contextInfo The servlet context helper info
+ * @param resourceInfo The resource info
+ */
+ public void registerResource(@Nonnull final ContextHandler contextHandler,
+ @Nonnull final ResourceInfo resourceInfo)
+ {
+ final ServletInfo servletInfo = new ServletInfo(resourceInfo, new ResourceServlet(resourceInfo.getPrefix()));
+
+ this.registerServlet(contextHandler, servletInfo);
+ }
+
+ /**
+ * Unregister a resource.
+ * @param contextInfo The servlet context helper info
+ * @param resourceInfo The resource info
+ */
+ public void unregisterResource(@Nonnull final ContextHandler contextHandler, @Nonnull final ResourceInfo resourceInfo)
+ {
+ final ServletInfo servletInfo = new ServletInfo(resourceInfo, null);
+ this.unregisterServlet(contextHandler, servletInfo);
+ }
+}
diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java
new file mode 100644
index 0000000..e7632b3
--- /dev/null
+++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java
@@ -0,0 +1,81 @@
+/*
+ * 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.tracker;
+
+import javax.servlet.ServletContextListener;
+
+import org.apache.felix.http.base.internal.logger.SystemLogger;
+import org.apache.felix.http.base.internal.runtime.ServletContextListenerInfo;
+import org.apache.felix.http.base.internal.whiteboard.ServletContextHelperManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+public final class ServletContextListenerTracker extends AbstractReferenceTracker<ServletContextListener>
+{
+ private final ServletContextHelperManager contextManager;
+
+ /** TODO Currently under discussion. */
+ private static final String OPT_IN_PROP = "osgi.http.whiteboard.listener";
+
+ private static org.osgi.framework.Filter createFilter(final BundleContext btx)
+ {
+ try
+ {
+ return btx.createFilter(String.format("(&(objectClass=%s)(%s=*))",
+ ServletContextListener.class.getName(),
+ OPT_IN_PROP));
+ }
+ catch ( final InvalidSyntaxException ise)
+ {
+ // we can safely ignore it as the above filter is a constant
+ }
+ return null; // we never get here - and if we get an NPE which is fine
+ }
+
+ public ServletContextListenerTracker(final BundleContext context, final ServletContextHelperManager manager)
+ {
+ super(context, createFilter(context));
+ this.contextManager = manager;
+ }
+
+ @Override
+ protected void added(final ServiceReference<ServletContextListener> ref)
+ {
+ final ServletContextListenerInfo info = new ServletContextListenerInfo(ref);
+
+ if ( info.isValid() )
+ {
+ this.contextManager.addWhiteboardService(info);
+ }
+ else
+ {
+ SystemLogger.debug("Ignoring Filter service " + ref);
+ }
+ }
+
+ @Override
+ protected void removed(final ServiceReference<ServletContextListener> ref)
+ {
+ final ServletContextListenerInfo info = new ServletContextListenerInfo(ref);
+
+ if ( info.isValid() )
+ {
+ this.contextManager.removeWhiteboardService(info);
+ }
+ }
+}