You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2015/02/01 12:37:36 UTC

svn commit: r1656283 - in /felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal: ./ runtime/ service/ whiteboard/ whiteboard/tracker/

Author: cziegeler
Date: Sun Feb  1 11:37:36 2015
New Revision: 1656283

URL: http://svn.apache.org/r1656283
Log:
FELIX-4545 : Implement Servlet Context Helper, more refactoring, add support for ServletContextListener services

Added:
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java   (with props)
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ContextHandler.java   (with props)
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/PerBundleServletContextImpl.java   (with props)
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/SharedServletContextImpl.java   (with props)
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardHttpService.java   (with props)
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java   (with props)
Removed:
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/InternalHttpService.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/ServletContextImpl.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ExtenderManager.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/HttpContextBridge.java
Modified:
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ContextInfo.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletContextHelperManager.java

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java?rev=1656283&r1=1656282&r2=1656283&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java Sun Feb  1 11:37:36 2015
@@ -31,8 +31,7 @@ import org.apache.felix.http.base.intern
 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 @@ public final class HttpServiceController
     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 @@ public final class HttpServiceController
         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 )

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ContextInfo.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ContextInfo.java?rev=1656283&r1=1656282&r2=1656283&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ContextInfo.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ContextInfo.java Sun Feb  1 11:37:36 2015
@@ -48,11 +48,24 @@ public final class ContextInfo extends A
         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()

Added: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java?rev=1656283&view=auto
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java (added)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java Sun Feb  1 11:37:36 2015
@@ -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);
+    }
+}

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletContextListenerInfo.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ContextHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ContextHandler.java?rev=1656283&view=auto
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ContextHandler.java (added)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ContextHandler.java Sun Feb  1 11:37:36 2015
@@ -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;
+    }
+
+}

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ContextHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ContextHandler.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ContextHandler.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/PerBundleServletContextImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/PerBundleServletContextImpl.java?rev=1656283&view=auto
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/PerBundleServletContextImpl.java (added)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/PerBundleServletContextImpl.java Sun Feb  1 11:37:36 2015
@@ -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();
+    }
+}

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/PerBundleServletContextImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/PerBundleServletContextImpl.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/PerBundleServletContextImpl.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletContextHelperManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletContextHelperManager.java?rev=1656283&r1=1656282&r2=1656283&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletContextHelperManager.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletContextHelperManager.java Sun Feb  1 11:37:36 2015
@@ -25,12 +25,14 @@ import java.util.Iterator;
 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 @@ import org.osgi.service.http.whiteboard.
 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 @@ public final class ServletContextHelperM
                 props);
     }
 
+    /**
+     * Clean up the instance
+     */
     public void close()
     {
         // TODO cleanup
@@ -99,32 +110,69 @@ public final class ServletContextHelperM
         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 final class ServletContextHelperM
      */
     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 @@ public final class ServletContextHelperM
     {
         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 @@ public final class ServletContextHelperM
     {
         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 @@ public final class ServletContextHelperM
     {
         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 @@ public final class ServletContextHelperM
      * @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 @@ public final class ServletContextHelperM
      * @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);
         }
     }
 }

Added: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/SharedServletContextImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/SharedServletContextImpl.java?rev=1656283&view=auto
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/SharedServletContextImpl.java (added)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/SharedServletContextImpl.java Sun Feb  1 11:37:36 2015
@@ -0,0 +1,412 @@
+/*
+ * 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.Collections;
+import java.util.Enumeration;
+import java.util.EventListener;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+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.SessionCookieConfig;
+import javax.servlet.SessionTrackingMode;
+import javax.servlet.descriptor.JspConfigDescriptor;
+
+import org.apache.felix.http.base.internal.logger.SystemLogger;
+
+/**
+ * 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 ServletContext context;
+    private final Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();
+
+    public SharedServletContextImpl(final ServletContext webContext)
+    {
+        this.context = webContext;
+    }
+
+    @Override
+    public ClassLoader getClassLoader()
+    {
+        // is implemented by {@link PerBundleServletContextImpl}.
+        return null;
+    }
+
+    /**
+     * @see javax.servlet.ServletContext#getResource(java.lang.String)
+     */
+    @Override
+    public URL getResource(String path)
+    {
+        // is implemented by {@link PerBundleServletContextImpl}.
+        return null;
+    }
+
+    @Override
+    public String getMimeType(String 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
+    public FilterRegistration.Dynamic addFilter(String filterName, Class<? extends Filter> type)
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public FilterRegistration.Dynamic addFilter(String filterName, Filter filter)
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public FilterRegistration.Dynamic addFilter(String filterName, String className)
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void addListener(Class<? extends EventListener> type)
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void addListener(String className)
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public <T extends EventListener> void addListener(T listener)
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> type)
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet)
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ServletRegistration.Dynamic addServlet(String servletName, String className)
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public <T extends Filter> T createFilter(Class<T> type) throws ServletException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public <T extends EventListener> T createListener(Class<T> type) throws ServletException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public <T extends Servlet> T createServlet(Class<T> type) throws ServletException
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void declareRoles(String... roleNames)
+    {
+        this.context.declareRoles(roleNames);
+    }
+
+    @Override
+    public String getVirtualServerName() {
+        return context.getVirtualServerName();
+    }
+
+    @Override
+    public Object getAttribute(String name)
+    {
+        return this.attributes.get(name);
+    }
+
+    @Override
+    public Enumeration getAttributeNames()
+    {
+        return Collections.enumeration(this.attributes.keySet());
+    }
+
+    @Override
+    public ServletContext getContext(String uri)
+    {
+        // TODO
+        return this.context.getContext(uri);
+    }
+
+    @Override
+    public String getContextPath()
+    {
+        // TODO
+        return this.context.getContextPath();
+    }
+
+    @Override
+    public Set<SessionTrackingMode> getDefaultSessionTrackingModes()
+    {
+        return this.context.getDefaultSessionTrackingModes();
+    }
+
+    @Override
+    public int getEffectiveMajorVersion()
+    {
+        return this.context.getEffectiveMajorVersion();
+    }
+
+    @Override
+    public int getEffectiveMinorVersion()
+    {
+        return this.context.getEffectiveMinorVersion();
+    }
+
+    @Override
+    public Set<SessionTrackingMode> getEffectiveSessionTrackingModes()
+    {
+        return this.context.getEffectiveSessionTrackingModes();
+    }
+
+    @Override
+    public FilterRegistration getFilterRegistration(String filterName)
+    {
+        return this.context.getFilterRegistration(filterName);
+    }
+
+    @Override
+    public Map<String, ? extends FilterRegistration> getFilterRegistrations()
+    {
+        return this.context.getFilterRegistrations();
+    }
+
+    @Override
+    public String getInitParameter(String name)
+    {
+        return this.context.getInitParameter(name);
+    }
+
+    @Override
+    public Enumeration getInitParameterNames()
+    {
+        return this.context.getInitParameterNames();
+    }
+
+    @Override
+    public JspConfigDescriptor getJspConfigDescriptor()
+    {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public int getMajorVersion()
+    {
+        return this.context.getMajorVersion();
+    }
+
+    @Override
+    public int getMinorVersion()
+    {
+        return this.context.getMinorVersion();
+    }
+
+    @Override
+    public RequestDispatcher getNamedDispatcher(String name)
+    {
+        return this.context.getNamedDispatcher(name);
+    }
+
+    @Override
+    public RequestDispatcher getRequestDispatcher(String uri)
+    {
+        return this.context.getRequestDispatcher(uri);
+    }
+
+    @Override
+    public InputStream getResourceAsStream(String path)
+    {
+        final URL res = getResource(path);
+        if (res != null)
+        {
+            try
+            {
+                return res.openStream();
+            }
+            catch (IOException e)
+            {
+                // Do nothing
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public String getServerInfo()
+    {
+        return this.context.getServerInfo();
+    }
+
+    @Override
+    public Servlet getServlet(String name) throws ServletException
+    {
+        return this.context.getServlet(name);
+    }
+
+    @Override
+    public String getServletContextName()
+    {
+        return this.context.getServletContextName();
+    }
+
+    @Override
+    public Enumeration getServletNames()
+    {
+        return this.context.getServletNames();
+    }
+
+    @Override
+    public ServletRegistration getServletRegistration(String servletName)
+    {
+        return this.context.getServletRegistration(servletName);
+    }
+
+    @Override
+    public Map<String, ? extends ServletRegistration> getServletRegistrations()
+    {
+        return this.context.getServletRegistrations();
+    }
+
+    @Override
+    public Enumeration getServlets()
+    {
+        return this.context.getServlets();
+    }
+
+    @Override
+    public SessionCookieConfig getSessionCookieConfig()
+    {
+        return this.context.getSessionCookieConfig();
+    }
+
+    @Override
+    public void log(Exception cause, String message)
+    {
+        SystemLogger.error(message, cause);
+    }
+
+    @Override
+    public void log(String message)
+    {
+        SystemLogger.info(message);
+    }
+
+    @Override
+    public void log(String message, Throwable cause)
+    {
+        SystemLogger.error(message, cause);
+    }
+
+    @Override
+    public void removeAttribute(String name)
+    {
+        Object oldValue = this.attributes.remove(name);
+
+        if (oldValue != null)
+        {
+            //this.attributeListener.attributeRemoved(new ServletContextAttributeEvent(this, name, oldValue));
+        }
+    }
+
+    @Override
+    public void setAttribute(String name, Object value)
+    {
+        if (value == null)
+        {
+            this.removeAttribute(name);
+        }
+        else if (name != null)
+        {
+            Object oldValue = this.attributes.put(name, value);
+
+            if (oldValue == null)
+            {
+                //this.attributeListener.attributeAdded(new ServletContextAttributeEvent(this, name, value));
+            }
+            else
+            {
+                //this.attributeListener.attributeReplaced(new ServletContextAttributeEvent(this, name, oldValue));
+            }
+        }
+    }
+
+    @Override
+    public boolean setInitParameter(String name, String value)
+    {
+        return this.context.setInitParameter(name, value);
+    }
+
+    @Override
+    public void setSessionTrackingModes(Set<SessionTrackingMode> modes)
+    {
+        this.context.setSessionTrackingModes(modes);
+    }
+}

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/SharedServletContextImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/SharedServletContextImpl.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/SharedServletContextImpl.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardHttpService.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardHttpService.java?rev=1656283&view=auto
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardHttpService.java (added)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardHttpService.java Sun Feb  1 11:37:36 2015
@@ -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);
+    }
+}

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardHttpService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardHttpService.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardHttpService.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java?rev=1656283&view=auto
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java (added)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java Sun Feb  1 11:37:36 2015
@@ -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);
+        }
+    }
+}

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextListenerTracker.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain