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/01/29 11:22:39 UTC

svn commit: r1655577 [1/2] - in /felix/sandbox/http-rfc189/base: ./ src/main/java/org/apache/felix/http/base/internal/ src/main/java/org/apache/felix/http/base/internal/handler/ src/main/java/org/apache/felix/http/base/internal/runtime/ src/main/java/o...

Author: cziegeler
Date: Thu Jan 29 10:22:38 2015
New Revision: 1655577

URL: http://svn.apache.org/r1655577
Log:
Move 189 whiteboard handling to base

Added:
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/runtime/
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/runtime/FilterInfo.java   (with props)
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletInfo.java   (with props)
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/AbstractMapping.java   (with props)
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/DefaultHttpContext.java   (with props)
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ExtenderManager.java   (with props)
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/FilterMapping.java   (with props)
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/HttpContextBridge.java   (with props)
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/HttpContextManager.java   (with props)
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ResourceMapping.java   (with props)
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletMapping.java   (with props)
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/AbstractTracker.java   (with props)
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/FilterTracker.java   (with props)
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ResourceTracker.java   (with props)
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletContextHelperTracker.java   (with props)
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ServletTracker.java   (with props)
Modified:
    felix/sandbox/http-rfc189/base/pom.xml
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java
    felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceRuntimeImpl.java
    felix/sandbox/http-rfc189/base/src/test/java/org/apache/felix/http/base/internal/handler/FilterHandlerTest.java
    felix/sandbox/http-rfc189/base/src/test/java/org/apache/felix/http/base/internal/handler/HandlerMappingTest.java
    felix/sandbox/http-rfc189/base/src/test/java/org/apache/felix/http/base/internal/handler/ServletHandlerTest.java

Modified: felix/sandbox/http-rfc189/base/pom.xml
URL: http://svn.apache.org/viewvc/felix/sandbox/http-rfc189/base/pom.xml?rev=1655577&r1=1655576&r2=1655577&view=diff
==============================================================================
--- felix/sandbox/http-rfc189/base/pom.xml (original)
+++ felix/sandbox/http-rfc189/base/pom.xml Thu Jan 29 10:22:38 2015
@@ -66,6 +66,7 @@
         <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
+            <version>6.0.0</version>
             <scope>provided</scope>
         </dependency>
         <dependency>

Modified: felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java
URL: http://svn.apache.org/viewvc/felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java?rev=1655577&r1=1655576&r2=1655577&view=diff
==============================================================================
--- felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java (original)
+++ felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/HttpServiceController.java Thu Jan 29 10:22:38 2015
@@ -33,6 +33,7 @@ import org.apache.felix.http.base.intern
 import org.apache.felix.http.base.internal.listener.ServletRequestAttributeListenerManager;
 import org.apache.felix.http.base.internal.listener.ServletRequestListenerManager;
 import org.apache.felix.http.base.internal.service.HttpServiceFactory;
+import org.apache.felix.http.base.internal.whiteboard.ExtenderManager;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.http.HttpService;
@@ -73,7 +74,8 @@ public final class HttpServiceController
     private final ServletContextListenerManager servletContextListener;
     private final boolean sharedContextAttributes;
     private final HttpServicePlugin plugin;
-    private ServiceRegistration serviceReg;
+    private volatile ExtenderManager manager;
+    private volatile ServiceRegistration serviceReg;
 
     public HttpServiceController(BundleContext bundleContext)
     {
@@ -156,10 +158,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((HttpService)factory.getService(this.bundleContext.getBundle(), this.serviceReg), this.bundleContext);
     }
 
     public void unregister()
     {
+        if ( this.manager != null )
+        {
+            this.manager.close();
+            this.manager = null;
+        }
+
         if (this.serviceReg == null)
         {
             return;

Modified: felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java
URL: http://svn.apache.org/viewvc/felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java?rev=1655577&r1=1655576&r2=1655577&view=diff
==============================================================================
--- felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java (original)
+++ felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java Thu Jan 29 10:22:38 2015
@@ -31,8 +31,8 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.felix.http.api.FilterInfo;
 import org.apache.felix.http.base.internal.context.ExtServletContext;
+import org.apache.felix.http.base.internal.runtime.FilterInfo;
 
 public final class FilterHandler extends AbstractHandler<FilterHandler>
 {
@@ -58,6 +58,7 @@ public final class FilterHandler extends
         setInitParams(filterInfo.initParams);
     }
 
+    @Override
     public int compareTo(FilterHandler other)
     {
         int thisRanking = this.filterInfo.ranking;
@@ -102,7 +103,7 @@ public final class FilterHandler extends
             return true;
         }
 
-        // FELIX-3988: If the response is not yet committed and still has the default 
+        // FELIX-3988: If the response is not yet committed and still has the default
         // status, we're going to override this and send an error instead.
         if (!res.isCommitted() && (res.getStatus() == SC_OK || res.getStatus() == 0))
         {

Modified: felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
URL: http://svn.apache.org/viewvc/felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java?rev=1655577&r1=1655576&r2=1655577&view=diff
==============================================================================
--- felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java (original)
+++ felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java Thu Jan 29 10:22:38 2015
@@ -29,8 +29,8 @@ import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.felix.http.api.ServletInfo;
 import org.apache.felix.http.base.internal.context.ExtServletContext;
+import org.apache.felix.http.base.internal.runtime.ServletInfo;
 
 /**
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
@@ -60,6 +60,7 @@ public class ServletHandler extends Abst
         setInitParams(servletInfo.initParams);
     }
 
+    @Override
     public int compareTo(ServletHandler other)
     {
         return getId() - other.getId();
@@ -115,7 +116,7 @@ public class ServletHandler extends Abst
             return true;
         }
 
-        // FELIX-3988: If the response is not yet committed and still has the default 
+        // FELIX-3988: If the response is not yet committed and still has the default
         // status, we're going to override this and send an error instead.
         if (!res.isCommitted() && (res.getStatus() == SC_OK || res.getStatus() == 0))
         {

Added: felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/runtime/FilterInfo.java
URL: http://svn.apache.org/viewvc/felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/runtime/FilterInfo.java?rev=1655577&view=auto
==============================================================================
--- felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/runtime/FilterInfo.java (added)
+++ felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/runtime/FilterInfo.java Thu Jan 29 10:22:38 2015
@@ -0,0 +1,104 @@
+/*
+ * 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 java.util.Map;
+
+import javax.servlet.DispatcherType;
+import javax.servlet.Filter;
+
+import org.osgi.dto.DTO;
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.http.runtime.dto.FilterDTO;
+
+import aQute.bnd.annotation.ConsumerType;
+
+/**
+ * Provides registration information for a {@link Filter}, and is used to programmatically register {@link Filter}s.
+ * <p>
+ * This class only provides information used at registration time, and as such differs slightly from {@link DTO}s like, {@link FilterDTO}.
+ * </p>
+ *
+ * TODO - we should move this to the same place as {@link ExtHttpServiceRuntime}.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@ConsumerType
+public final class FilterInfo
+{
+    /**
+     * The name of the servlet.
+     */
+    public String name;
+
+    /**
+     * The request mappings for the servlet.
+     * <p>
+     * The specified patterns are used to determine whether a request is mapped to the servlet filter.<br>
+     * Note that these patterns should conform to the Servlet specification.
+     * </p>
+     */
+    public String[] patterns;
+
+    /**
+     * The servlet names for the servlet filter.
+     * <p>
+     * The specified names are used to determine the servlets whose requests are mapped to the servlet filter.
+     * </p>
+     */
+    public String[] servletNames;
+
+    /**
+     * The request mappings for the servlet filter.
+     * <p>
+     * The specified regular expressions are used to determine whether a request is mapped to the servlet filter.<br>
+     * These regular expressions are a convenience extension allowing one to specify filters that match paths that are difficult to match with plain Servlet patterns alone.
+     * </p>
+     */
+    public String[] regexs;
+
+    /**
+     * Specifies whether the servlet filter supports asynchronous processing.
+     */
+    public boolean asyncSupported = false;
+
+    /**
+     * Specifies the ranking order in which this filter should be called. Higher rankings are called first.
+     */
+    public int ranking = 0;
+
+    /**
+     * The dispatcher associations for the servlet filter.
+     * <p>
+     * The specified names are used to determine in what occasions the servlet filter is called.
+     * See {@link DispatcherType} and Servlet 3.0 specification, section 6.2.5.
+     * </p>
+     */
+    public DispatcherType[] dispatcher = { DispatcherType.REQUEST };
+
+    /**
+     * The filter initialization parameters as provided during registration of the filter.
+     */
+    public Map<String, String> initParams;
+
+    /**
+     * The {@link HttpContext} for the servlet.
+     */
+    public HttpContext context;
+
+}

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

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

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

Added: felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletInfo.java
URL: http://svn.apache.org/viewvc/felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletInfo.java?rev=1655577&view=auto
==============================================================================
--- felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletInfo.java (added)
+++ felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/runtime/ServletInfo.java Thu Jan 29 10:22:38 2015
@@ -0,0 +1,76 @@
+/*
+ * 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 java.util.Map;
+
+import javax.servlet.Servlet;
+
+import org.osgi.dto.DTO;
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.http.runtime.dto.ServletDTO;
+
+import aQute.bnd.annotation.ConsumerType;
+
+/**
+ * Provides registration information for a {@link Servlet}, and is used to programmatically register {@link Servlet}s.
+ * <p>
+ * This class only provides information used at registration time, and as such differs slightly from {@link DTO}s like, {@link ServletDTO}.
+ * </p>
+ *
+ * TODO - we should move this to the same place as {@link ExtHttpServiceRuntime}.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+@ConsumerType
+public final class ServletInfo
+{
+    /**
+     * The name of the servlet.
+     */
+    public String name;
+
+    /**
+     * The request mappings for the servlet.
+     * <p>
+     * The specified patterns are used to determine whether a request is mapped to the servlet.
+     * </p>
+     */
+    public String[] patterns;
+
+    /**
+     * The error pages and/or codes.
+     */
+    public String[] errorPage;
+
+    /**
+     * Specifies whether the servlet supports asynchronous processing.
+     */
+    public boolean asyncSupported = false;
+
+    /**
+     * The servlet initialization parameters as provided during registration of the servlet.
+     */
+    public Map<String, String> initParams;
+
+    /**
+     * The {@link HttpContext} for the servlet.
+     */
+    public HttpContext context;
+
+}

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

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

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

Modified: felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java?rev=1655577&r1=1655576&r2=1655577&view=diff
==============================================================================
--- felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java (original)
+++ felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java Thu Jan 29 10:22:38 2015
@@ -29,14 +29,14 @@ import javax.servlet.ServletContextAttri
 import javax.servlet.ServletException;
 
 import org.apache.felix.http.api.ExtHttpService;
-import org.apache.felix.http.api.FilterInfo;
-import org.apache.felix.http.api.ServletInfo;
 import org.apache.felix.http.base.internal.context.ExtServletContext;
 import org.apache.felix.http.base.internal.context.ServletContextManager;
 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.logger.SystemLogger;
+import org.apache.felix.http.base.internal.runtime.FilterInfo;
+import org.apache.felix.http.base.internal.runtime.ServletInfo;
 import org.osgi.framework.Bundle;
 import org.osgi.service.http.HttpContext;
 import org.osgi.service.http.NamespaceException;
@@ -84,6 +84,7 @@ public final class HttpServiceImpl imple
         return str == null || "".equals(str.trim());
     }
 
+    @Override
     public HttpContext createDefaultHttpContext()
     {
         return new DefaultHttpContext(this.bundle);
@@ -135,6 +136,7 @@ public final class HttpServiceImpl imple
         }
     }
 
+    @Override
     public void registerFilter(Filter filter, String pattern, Dictionary initParams, int ranking, HttpContext context) throws ServletException
     {
         FilterInfo filterInfo = new FilterInfo();
@@ -146,6 +148,7 @@ public final class HttpServiceImpl imple
         registerFilter(filter, filterInfo);
     }
 
+    @Override
     public void registerResources(String alias, String name, HttpContext context) throws NamespaceException
     {
         if (!isNameValid(name))
@@ -221,6 +224,7 @@ public final class HttpServiceImpl imple
         }
     }
 
+    @Override
     public void registerServlet(String alias, Servlet servlet, Dictionary initParams, HttpContext context) throws ServletException, NamespaceException
     {
         ServletInfo servletInfo = new ServletInfo();
@@ -231,6 +235,7 @@ public final class HttpServiceImpl imple
         registerServlet(servlet, servletInfo);
     }
 
+    @Override
     public synchronized void unregister(String alias)
     {
         // TODO this can also be a filter or a resource?!
@@ -266,11 +271,13 @@ public final class HttpServiceImpl imple
         }
     }
 
+    @Override
     public synchronized void unregisterFilter(Filter filter)
     {
         unregisterFilter(filter, true);
     }
 
+    @Override
     public synchronized void unregisterServlet(Servlet servlet)
     {
         unregisterServlet(servlet, true);

Modified: felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceRuntimeImpl.java
URL: http://svn.apache.org/viewvc/felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceRuntimeImpl.java?rev=1655577&r1=1655576&r2=1655577&view=diff
==============================================================================
--- felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceRuntimeImpl.java (original)
+++ felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceRuntimeImpl.java Thu Jan 29 10:22:38 2015
@@ -16,7 +16,7 @@
  */
 package org.apache.felix.http.base.internal.service;
 
-import org.apache.felix.http.api.ExtHttpServiceRuntime;
+import org.osgi.service.http.runtime.HttpServiceRuntime;
 import org.osgi.service.http.runtime.dto.ErrorPageDTO;
 import org.osgi.service.http.runtime.dto.FailedErrorPageDTO;
 import org.osgi.service.http.runtime.dto.FailedFilterDTO;
@@ -26,9 +26,10 @@ import org.osgi.service.http.runtime.dto
 import org.osgi.service.http.runtime.dto.RuntimeDTO;
 import org.osgi.service.http.runtime.dto.ServletDTO;
 
-public final class HttpServiceRuntimeImpl implements ExtHttpServiceRuntime
+public final class HttpServiceRuntimeImpl implements HttpServiceRuntime
 {
 
+    @Override
     public RuntimeDTO getRuntimeDTO()
     {
         // TODO
@@ -65,6 +66,7 @@ public final class HttpServiceRuntimeImp
         // TODO
     }
 
+    @Override
     public RequestInfoDTO calculateRequestInfoDTO(String path) {
         // TODO
         return null;

Added: felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/AbstractMapping.java
URL: http://svn.apache.org/viewvc/felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/AbstractMapping.java?rev=1655577&view=auto
==============================================================================
--- felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/AbstractMapping.java (added)
+++ felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/AbstractMapping.java Thu Jan 29 10:22:38 2015
@@ -0,0 +1,74 @@
+/*
+ * 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.Hashtable;
+
+import org.osgi.framework.Bundle;
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.http.HttpService;
+
+abstract class AbstractMapping
+{
+    private final Bundle bundle;
+    private HttpContext context;
+    private final Hashtable<String, String> initParams;
+    private boolean registered;
+
+    protected AbstractMapping(final Bundle bundle)
+    {
+        this.bundle = bundle;
+        this.context = null;
+        this.initParams = new Hashtable<String, String>();
+        this.registered = false;
+    }
+
+    public Bundle getBundle()
+    {
+        return bundle;
+    }
+
+    public void setContext(HttpContext context)
+    {
+        this.context = context;
+    }
+
+    public final HttpContext getContext()
+    {
+        return this.context;
+    }
+
+    public final Hashtable<String, String> getInitParams()
+    {
+        return this.initParams;
+    }
+
+    boolean isRegistered()
+    {
+        return registered;
+    }
+
+    void setRegistered(boolean registered)
+    {
+        this.registered = registered;
+    }
+
+    public abstract void register(HttpService httpService);
+
+    public abstract void unregister(HttpService httpService);
+
+}

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

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

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

Added: felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/DefaultHttpContext.java
URL: http://svn.apache.org/viewvc/felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/DefaultHttpContext.java?rev=1655577&view=auto
==============================================================================
--- felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/DefaultHttpContext.java (added)
+++ felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/DefaultHttpContext.java Thu Jan 29 10:22:38 2015
@@ -0,0 +1,59 @@
+/*
+ * 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.framework.Bundle;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.net.URL;
+
+public final class DefaultHttpContext
+    implements HttpContext
+{
+    private Bundle bundle;
+
+    public DefaultHttpContext(Bundle bundle)
+    {
+        this.bundle = bundle;
+    }
+
+    public String getMimeType(String name)
+    {
+        return null;
+    }
+
+    public URL getResource(String name)
+    {
+        if (name.startsWith("/")) {
+            name = name.substring(1);
+        }
+
+        return this.bundle.getResource(name);
+    }
+
+    public boolean handleSecurity(HttpServletRequest req, HttpServletResponse res)
+    {
+        return true;
+    }
+
+    @Override
+    public String toString()
+    {
+        return getClass().getSimpleName() + " (" + Integer.toHexString(System.identityHashCode(this)) + ")";
+    }
+}
\ No newline at end of file

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

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

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

Added: felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ExtenderManager.java
URL: http://svn.apache.org/viewvc/felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ExtenderManager.java?rev=1655577&view=auto
==============================================================================
--- felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ExtenderManager.java (added)
+++ felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ExtenderManager.java Thu Jan 29 10:22:38 2015
@@ -0,0 +1,453 @@
+/*
+ * 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 java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.DispatcherType;
+import javax.servlet.Filter;
+import javax.servlet.Servlet;
+
+import org.apache.felix.http.base.internal.logger.SystemLogger;
+import org.apache.felix.http.base.internal.runtime.FilterInfo;
+import org.apache.felix.http.base.internal.runtime.ServletInfo;
+import org.apache.felix.http.base.internal.whiteboard.HttpContextManager.HttpContextHolder;
+import org.apache.felix.http.base.internal.whiteboard.tracker.FilterTracker;
+import org.apache.felix.http.base.internal.whiteboard.tracker.ServletContextHelperTracker;
+import org.apache.felix.http.base.internal.whiteboard.tracker.ServletTracker;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.http.HttpService;
+import org.osgi.service.http.context.ServletContextHelper;
+import org.osgi.service.http.runtime.dto.ResourceDTO;
+import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
+import org.osgi.util.tracker.ServiceTracker;
+
+@SuppressWarnings({ "deprecation" })
+public final class ExtenderManager
+{
+    static final String TYPE_FILTER = "f";
+    static final String TYPE_SERVLET = "s";
+    static final String TYPE_RESOURCE = "r";
+
+    /**
+     * Properties starting with this prefix are passed as servlet init parameters to the
+     * {@code init()} method of the servlet.
+     */
+    public static final String SERVLET_INIT_PREFIX = "servlet.init.";
+
+    /**
+     * Properties starting with this prefix are passed as filter
+     * init parameters to the {@code init()} method of the filter.
+     */
+    public static final String FILTER_INIT_PREFIX = "filter.init.";
+
+    private final Map<String, AbstractMapping> mapping;
+    private final HttpContextManager contextManager;
+
+    private final HttpService httpService;
+
+    private final ArrayList<ServiceTracker> trackers = new ArrayList<ServiceTracker>();
+
+    public ExtenderManager(final HttpService httpService, final BundleContext bundleContext)
+    {
+        this.mapping = new HashMap<String, AbstractMapping>();
+        this.contextManager = new HttpContextManager();
+        this.httpService = httpService;
+        addTracker(new FilterTracker(bundleContext, this));
+        addTracker(new ServletTracker(bundleContext, this));
+        addTracker(new ServletContextHelperTracker(bundleContext, this));
+    }
+
+    public void close()
+    {
+        for(final ServiceTracker t : this.trackers)
+        {
+            t.close();
+        }
+        this.trackers.clear();
+        this.unregisterAll();
+    }
+
+    private void addTracker(ServiceTracker tracker)
+    {
+        this.trackers.add(tracker);
+        tracker.open();
+    }
+
+    static boolean isEmpty(final String value)
+    {
+        return value == null || value.length() == 0;
+    }
+
+    static boolean isEmpty(final String[] value)
+    {
+        return value == null || value.length == 0;
+    }
+
+    private String getStringProperty(ServiceReference ref, String key)
+    {
+        Object value = ref.getProperty(key);
+        return (value instanceof String) ? (String) value : null;
+    }
+
+    private String[] getStringArrayProperty(ServiceReference ref, String key)
+    {
+        Object value = ref.getProperty(key);
+
+        if (value instanceof String)
+        {
+            return new String[] { (String) value };
+        }
+        else if (value instanceof String[])
+        {
+            return (String[]) value;
+        }
+        else if (value instanceof Collection<?>)
+        {
+            Collection<?> collectionValues = (Collection<?>) value;
+            String[] values = new String[collectionValues.size()];
+
+            int i = 0;
+            for (Object current : collectionValues)
+            {
+                values[i++] = current != null ? String.valueOf(current) : null;
+            }
+
+            return values;
+        }
+
+        return null;
+    }
+
+    private boolean getBooleanProperty(ServiceReference ref, String key)
+    {
+        Object value = ref.getProperty(key);
+        if (value instanceof String)
+        {
+            return Boolean.valueOf((String) value);
+        }
+        else if (value instanceof Boolean)
+        {
+            return ((Boolean) value).booleanValue();
+        }
+        return false;
+    }
+
+    private int getIntProperty(ServiceReference ref, String key, int defValue)
+    {
+        Object value = ref.getProperty(key);
+        if (value == null)
+        {
+            return defValue;
+        }
+
+        try
+        {
+            return Integer.parseInt(value.toString());
+        }
+        catch (Exception e)
+        {
+            return defValue;
+        }
+    }
+
+    private void addInitParams(ServiceReference ref, AbstractMapping mapping)
+    {
+        for (String key : ref.getPropertyKeys())
+        {
+            String prefixKey = null;
+
+            if (mapping instanceof FilterMapping && key.startsWith(FILTER_INIT_PREFIX))
+            {
+                prefixKey = FILTER_INIT_PREFIX;
+            }
+            else if (mapping instanceof ServletMapping && key.startsWith(SERVLET_INIT_PREFIX))
+            {
+                prefixKey = SERVLET_INIT_PREFIX;
+            }
+
+            if (prefixKey != null)
+            {
+                String paramKey = key.substring(prefixKey.length());
+                String paramValue = getStringProperty(ref, key);
+
+                if (paramValue != null)
+                {
+                    mapping.getInitParams().put(paramKey, paramValue);
+                }
+            }
+        }
+    }
+
+    public void add(ServletContextHelper service, ServiceReference ref)
+    {
+        String name = getStringProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME);
+        String path = getStringProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH);
+
+        // TODO - check if name and path are valid values
+        if (!isEmpty(name) && !isEmpty(path) )
+        {
+            Collection<AbstractMapping> mappings = this.contextManager.addContextHelper(ref.getBundle(), name, path, service);
+            for (AbstractMapping mapping : mappings)
+            {
+                registerMapping(mapping);
+            }
+        }
+        else
+        {
+            SystemLogger.debug("Ignoring ServletContextHelper Service " + ref + ", " + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + " is missing or empty");
+        }
+    }
+
+    public void addResource(final ServiceReference ref)
+    {
+        final String[] pattern = getStringArrayProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN);
+        final String prefix = getStringProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX);
+
+        if (!isEmpty(pattern))
+        {
+            if ( !isEmpty(prefix))
+            {
+                for(final String p : pattern)
+                {
+                    // TODO : check if p is empty - and then log?
+                    final ResourceDTO resourceDTO = new ResourceDTO();
+                    resourceDTO.patterns = new String[] {p};
+                    resourceDTO.prefix = prefix;
+                    final ResourceMapping mapping = new ResourceMapping(ref.getBundle(), resourceDTO);
+                    this.addMapping(TYPE_RESOURCE, ref, mapping);
+                }
+            }
+            else
+            {
+                SystemLogger.debug("Ignoring Resource Service " + ref + ", " + HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX + " is missing or empty");
+            }
+        }
+        else
+        {
+            SystemLogger.debug("Ignoring Resource Service " + ref + ", " + HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN + " is missing or empty");
+        }
+    }
+
+    public void removeResource(final ServiceReference ref)
+    {
+        this.removeMapping(TYPE_RESOURCE, ref);
+    }
+
+    public void remove(ServletContextHelper service)
+    {
+        Collection<AbstractMapping> mappings = this.contextManager.removeContextHelper(service);
+        if (mappings != null)
+        {
+            for (AbstractMapping mapping : mappings)
+            {
+                unregisterMapping(mapping);
+            }
+        }
+    }
+
+    private HttpContext getHttpContext(AbstractMapping mapping, ServiceReference ref)
+    {
+        Bundle bundle = ref.getBundle();
+        String contextName = getStringProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT);
+        if (!isEmpty(contextName))
+        {
+            return this.contextManager.getHttpContext(bundle, contextName, mapping, true);
+        }
+        return this.contextManager.getHttpContext(bundle, null, mapping);
+    }
+
+    private void ungetHttpContext(AbstractMapping mapping, ServiceReference ref)
+    {
+        Bundle bundle = ref.getBundle();
+        String contextName = getStringProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT);
+        if (!isEmpty(contextName))
+        {
+            this.contextManager.ungetHttpContext(bundle, contextName, mapping, true);
+            return;
+        }
+        this.contextManager.ungetHttpContext(bundle, null, mapping);
+    }
+
+    public void add(final Filter service, final ServiceReference ref)
+    {
+        FilterInfo filterInfo = new FilterInfo();
+        filterInfo.name = getStringProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_NAME);
+        if ( filterInfo.name == null || filterInfo.name.isEmpty() )
+        {
+            filterInfo.name = service.getClass().getName();
+        }
+        filterInfo.asyncSupported = getBooleanProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_ASYNC_SUPPORTED);
+        filterInfo.servletNames = getStringArrayProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_SERVLET);
+        filterInfo.patterns = getStringArrayProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN);
+        filterInfo.ranking = getIntProperty(ref, Constants.SERVICE_RANKING, 0);
+
+        String[] dispatcherNames = getStringArrayProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_DISPATCHER);
+        if (dispatcherNames != null && dispatcherNames.length > 0)
+        {
+            DispatcherType[] dispatchers = new DispatcherType[dispatcherNames.length];
+            for (int i = 0; i < dispatchers.length; i++)
+            {
+                dispatchers[i] = DispatcherType.valueOf(dispatcherNames[i].toUpperCase());
+            }
+            filterInfo.dispatcher = dispatchers;
+        }
+
+        if (isEmpty(filterInfo.patterns))
+        {
+            SystemLogger.debug("Ignoring Filter Service " + ref + ", " + HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN +
+                    " is missing or empty");
+            return;
+        }
+
+        FilterMapping mapping = new FilterMapping(ref.getBundle(), service, filterInfo);
+        filterInfo.context = getHttpContext(mapping, ref); // XXX
+        addInitParams(ref, mapping);
+        addMapping(TYPE_FILTER, ref, mapping);
+    }
+
+    public void add(Servlet service, ServiceReference ref)
+    {
+        ServletInfo servletInfo = new ServletInfo();
+        servletInfo.name = getStringProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME);
+        if ( servletInfo.name == null || servletInfo.name.isEmpty() )
+        {
+            servletInfo.name = service.getClass().getName();
+        }
+        servletInfo.errorPage = getStringArrayProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ERROR_PAGE);
+        servletInfo.patterns = getStringArrayProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN);
+        servletInfo.asyncSupported = getBooleanProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED);
+
+        if (isEmpty(servletInfo.patterns))
+        {
+            SystemLogger.debug("Ignoring Servlet Service " + ref + ", " + HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN +
+                    "is missing or empty");
+            return;
+        }
+
+        final ServletMapping mapping = new ServletMapping(ref.getBundle(), service, servletInfo);
+        servletInfo.context = getHttpContext(mapping, ref); // XXX
+        addInitParams(ref, mapping);
+        addMapping(TYPE_SERVLET, ref, mapping);
+    }
+
+    public void removeFilter(ServiceReference ref)
+    {
+        removeMapping(TYPE_FILTER, ref);
+    }
+
+    public void removeServlet(ServiceReference ref)
+    {
+        removeMapping(TYPE_SERVLET, ref);
+    }
+
+    private synchronized void unregisterAll()
+    {
+        AbstractMapping[] mappings = null;
+        HttpService service;
+        synchronized (this)
+        {
+            service = this.httpService;
+            if (service != null)
+            {
+                Collection<AbstractMapping> values = this.mapping.values();
+                mappings = values.toArray(new AbstractMapping[values.size()]);
+            }
+        }
+        if (mappings != null)
+        {
+            for (AbstractMapping mapping : mappings)
+            {
+                mapping.unregister(service);
+            }
+        }
+    }
+
+    private synchronized void addMapping(final String servType, ServiceReference ref, AbstractMapping mapping)
+    {
+        this.mapping.put(ref.getProperty(Constants.SERVICE_ID).toString().concat(servType), mapping);
+        this.registerMapping(mapping);
+    }
+
+    private synchronized void removeMapping(final String servType, ServiceReference ref)
+    {
+        AbstractMapping mapping = this.mapping.remove(ref.getProperty(Constants.SERVICE_ID).toString().concat(servType));
+        if (mapping != null)
+        {
+            ungetHttpContext(mapping, ref);
+            unregisterMapping(mapping);
+        }
+    }
+
+    private void registerMapping(AbstractMapping mapping)
+    {
+        HttpService httpService = this.httpService;
+        if (httpService != null)
+        {
+            mapping.register(httpService);
+        }
+    }
+
+    private void unregisterMapping(AbstractMapping mapping)
+    {
+        HttpService httpService = this.httpService;
+        if (httpService != null)
+        {
+            mapping.unregister(httpService);
+        }
+    }
+
+    /**
+     * Returns
+     * {@link org.apache.felix.http.base.internal.whiteboard.whiteboard.internal.manager.HttpContextManager.HttpContextHolder}
+     * instances of HttpContext services.
+     *
+     * @return
+     */
+    Map<String, HttpContextHolder> getHttpContexts()
+    {
+        return this.contextManager.getHttpContexts();
+    }
+
+    /**
+     * Returns {@link AbstractMapping} instances for which there is no
+     * registered HttpContext as desired by the context ID.
+     */
+    Map<String, Set<AbstractMapping>> getOrphanMappings()
+    {
+        return this.contextManager.getOrphanMappings();
+    }
+
+    /**
+     * Returns mappings indexed by there owning OSGi service.
+     */
+    Map<String, AbstractMapping> getMappings()
+    {
+        synchronized (this)
+        {
+            return new HashMap<String, AbstractMapping>(this.mapping);
+        }
+    }
+}

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

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

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

Added: felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/FilterMapping.java
URL: http://svn.apache.org/viewvc/felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/FilterMapping.java?rev=1655577&view=auto
==============================================================================
--- felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/FilterMapping.java (added)
+++ felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/FilterMapping.java Thu Jan 29 10:22:38 2015
@@ -0,0 +1,110 @@
+/*
+ * 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 javax.servlet.Filter;
+
+import org.apache.felix.http.base.internal.logger.SystemLogger;
+import org.apache.felix.http.base.internal.runtime.FilterInfo;
+import org.apache.felix.http.base.internal.service.HttpServiceImpl;
+import org.osgi.framework.Bundle;
+import org.osgi.service.http.HttpService;
+
+public final class FilterMapping extends AbstractMapping
+{
+    private final Filter filter;
+    private final FilterInfo filterInfo;
+
+    public FilterMapping(Bundle bundle, Filter filter, FilterInfo filterInfo)
+    {
+        super(bundle);
+        this.filter = filter;
+        this.filterInfo = filterInfo;
+    }
+
+    @Override
+    public void register(HttpService httpService)
+    {
+        if (!isRegistered() && (httpService instanceof HttpServiceImpl) && getContext() != null)
+        {
+            register((HttpServiceImpl) httpService);
+        }
+        else
+        {
+            // Warn the user that something strange is going on...
+            SystemLogger.warning("Unable to register filter for " + this.filterInfo.name + ", as no ExtHttpService seems to be present!", null);
+        }
+    }
+
+    @Override
+    public void unregister(HttpService httpService)
+    {
+        if (isRegistered() && (httpService instanceof HttpServiceImpl))
+        {
+            unregister((HttpServiceImpl) httpService);
+        }
+        else
+        {
+            // Warn the user that something strange is going on...
+            SystemLogger.warning("Unable to unregister filter for " + this.filterInfo.name + ", as no ExtHttpService seems to be present!", null);
+        }
+    }
+
+    Filter getFilter()
+    {
+        return filter;
+    }
+
+    private void register(HttpServiceImpl httpService)
+    {
+        if (!isRegistered() && getContext() != null)
+        {
+            try
+            {
+                httpService.registerFilter(this.filter, this.filterInfo);
+                setRegistered(true);
+            }
+            catch (Exception e)
+            {
+                // Warn that something might have gone astray...
+                SystemLogger.warning("Failed to register filter for " + this.filterInfo.name, null);
+                SystemLogger.debug("Failed to register filter for " + this.filterInfo.name + "; details:", e);
+            }
+        }
+    }
+
+    private void unregister(HttpServiceImpl httpService)
+    {
+        if (isRegistered())
+        {
+            try
+            {
+                httpService.unregisterFilter(this.filter);
+            }
+            catch (Exception e)
+            {
+                // Warn that something might have gone astray...
+                SystemLogger.debug("Failed to unregister filter for " + this.filterInfo.name, e);
+            }
+            finally
+            {
+                // Best effort: avoid mappings that are registered which is reality aren't registered...
+                setRegistered(false);
+            }
+        }
+    }
+}

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

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

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

Added: felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/HttpContextBridge.java
URL: http://svn.apache.org/viewvc/felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/HttpContextBridge.java?rev=1655577&view=auto
==============================================================================
--- felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/HttpContextBridge.java (added)
+++ felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/HttpContextBridge.java Thu Jan 29 10:22:38 2015
@@ -0,0 +1,71 @@
+/*
+ * 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;
+
+    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;
+    }
+}

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

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

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

Added: felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/HttpContextManager.java
URL: http://svn.apache.org/viewvc/felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/HttpContextManager.java?rev=1655577&view=auto
==============================================================================
--- felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/HttpContextManager.java (added)
+++ felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/HttpContextManager.java Thu Jan 29 10:22:38 2015
@@ -0,0 +1,357 @@
+/*
+ * 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.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.felix.http.base.internal.logger.SystemLogger;
+import org.osgi.framework.Bundle;
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.http.context.ServletContextHelper;
+
+public final class HttpContextManager
+{
+    /**
+     * HttpContextHolders indexed by context ID fully configured
+     * with an HttpContext and optional servlets and filters.
+     * <p>
+     * The context ID either includes the bundle ID as the first part of the
+     * name, such as <i>123-sample.context</i> in the case of non-shared
+     * contexts. IDs of shared contexts are prefixed with the fixed string
+     * <code>shared</code> to not mix them with per-bundle contexts.
+     */
+    private final HashMap<String, HttpContextHolder> idMap;
+
+    /**
+     * Reverse mapping of HttpContext services to the context ID or
+     * name with which they are registered.
+     */
+    private final HashMap<HttpContext, String> contextMap;
+
+    /**
+     * Mapping of registered ServletContextHelper services to the
+     * HttpContext stored in <code>contextMap</code>.
+     */
+    private final HashMap<ServletContextHelper, HttpContext> helperMap;
+
+    /**
+     * Map of servlets and filters registered referring to unregistered
+     * contexts as of yet.
+     */
+    private final HashMap<String, Set<AbstractMapping>> orphanMappings;
+
+    public HttpContextManager()
+    {
+        this.idMap = new HashMap<String, HttpContextHolder>();
+        this.contextMap = new HashMap<HttpContext, String>();
+        this.helperMap = new HashMap<ServletContextHelper, HttpContext>();
+        this.orphanMappings = new HashMap<String, Set<AbstractMapping>>();
+    }
+
+    private static String createId(Bundle bundle, String contextId, boolean isContextHelper)
+    {
+        if (isContextHelper)
+        {
+            return "servletcontexthelper-" + ((contextId == null) ? "" : contextId);
+        }
+        if (bundle != null)
+        {
+            return bundle.getBundleId() + "-" + ((contextId == null) ? "" : contextId);
+        }
+
+        return createId(contextId);
+    }
+
+    private static String createId(String contextId)
+    {
+        return "shared-" + ((contextId == null) ? "" : contextId);
+    }
+
+    private static String getContextId(String id)
+    {
+        final int dash = id.indexOf('-');
+        return (dash < 0) ? id : id.substring(dash + 1);
+    }
+
+    public synchronized HttpContext getHttpContext(Bundle bundle, String contextId, AbstractMapping mapping)
+    {
+        return getHttpContext(bundle, contextId, mapping, false);
+    }
+
+    public synchronized HttpContext getHttpContext(Bundle bundle, String contextId, AbstractMapping mapping,
+                                                   boolean isContextHelper)
+    {
+        // per-bundle context
+        String id = createId(bundle, contextId, isContextHelper);
+        HttpContextHolder holder = this.idMap.get(id);
+
+        // shared context
+        if (holder == null)
+        {
+            id = createId(contextId);
+            holder = this.idMap.get(id);
+        }
+
+        // no context yet, put the mapping on hold
+        if (holder == null)
+        {
+            // care for default context if no context ID
+            if (ExtenderManager.isEmpty(contextId))
+            {
+                addHttpContext(bundle, "", new DefaultHttpContext(bundle));
+                return getHttpContext(bundle, "", mapping);
+            }
+
+            // otherwise context is not here yet
+            Set<AbstractMapping> orphaned = this.orphanMappings.get(contextId);
+            if (orphaned == null)
+            {
+                orphaned = new HashSet<AbstractMapping>();
+                this.orphanMappings.put(contextId, orphaned);
+            }
+            if (contextId != null)
+            {
+                // Only log something when an actual context ID is used. Should solve FELIX-4307...
+                SystemLogger.debug("Holding off mapping with unregistered context with id [" + contextId + "]");
+            }
+            orphaned.add(mapping);
+            return null;
+        }
+
+        // otherwise use the context
+        if (contextId != null)
+        {
+            // Only log something when an actual context ID is used. Should solve FELIX-4307...
+            SystemLogger.debug("Reusing context with id [" + contextId + "]");
+        }
+
+        holder.addMapping(mapping);
+        return holder.getContext();
+    }
+
+    public synchronized void ungetHttpContext(Bundle bundle, String contextId, AbstractMapping mapping)
+    {
+        ungetHttpContext(bundle, contextId, mapping, false);
+    }
+
+    public synchronized void ungetHttpContext(Bundle bundle, String contextId,
+                                              AbstractMapping mapping, boolean isContextHelper)
+    {
+        // per-bundle context
+        String id = createId(bundle, contextId, isContextHelper);
+        HttpContextHolder context = this.idMap.get(id);
+
+        // shared context
+        if (context == null && !isContextHelper)
+        {
+            id = createId(contextId);
+            context = this.idMap.get(id);
+        }
+
+        // remove the mapping if there is a mapped context
+        if (context != null)
+        {
+            context.removeMapping(mapping);
+        }
+        else
+        {
+            Set<AbstractMapping> orphans = this.orphanMappings.get(contextId);
+            if (orphans != null)
+            {
+                orphans.remove(mapping);
+                if (orphans.isEmpty())
+                {
+                    this.orphanMappings.remove(contextId);
+                }
+            }
+
+            // it is not expected but make sure there is no reference
+            mapping.setContext(null);
+        }
+    }
+
+    public synchronized Collection<AbstractMapping> addHttpContext(Bundle bundle, String contextId, HttpContext context)
+    {
+        String id = createId(bundle, contextId, false);
+        HttpContextHolder holder = new HttpContextHolder(context);
+
+        Set<AbstractMapping> orphans = this.orphanMappings.remove(contextId);
+        if (orphans != null)
+        {
+            for (Iterator<AbstractMapping> mi = orphans.iterator(); mi.hasNext();)
+            {
+                AbstractMapping mapping = mi.next();
+                if (bundle == null || bundle.equals(mapping.getBundle()))
+                {
+                    holder.addMapping(mapping);
+                    mi.remove();
+                }
+            }
+
+            // put any remaining orphans back
+            if (!orphans.isEmpty())
+            {
+                this.orphanMappings.put(contextId, orphans);
+            }
+        }
+
+        this.idMap.put(id, holder);
+        this.contextMap.put(context, id);
+        
+        // return a copy to prevent concurrent modification
+        return new HashSet<AbstractMapping>(holder.getMappings());
+    }
+
+    public synchronized Collection<AbstractMapping> addContextHelper(Bundle bundle, String contextName, String contextPath,
+                                                                     ServletContextHelper contextHelper)
+    {
+        String id = createId(bundle, contextName, true);
+        HttpContextHolder holder = new HttpContextHolder(contextHelper, contextPath);
+
+        Set<AbstractMapping> orphans = this.orphanMappings.remove(contextName);
+        if (orphans != null)
+        {
+            for (Iterator<AbstractMapping> mi = orphans.iterator(); mi.hasNext();)
+            {
+                AbstractMapping mapping = mi.next();
+                if (bundle == null || bundle.equals(mapping.getBundle()))
+                {
+                    holder.addMapping(mapping);
+                    mi.remove();
+                }
+            }
+
+            // put any remaining orphans back
+            if (!orphans.isEmpty())
+            {
+                this.orphanMappings.put(contextName, orphans);
+            }
+        }
+
+        this.idMap.put(id, holder);
+        this.contextMap.put(holder.getContext(), id);
+        this.helperMap.put(contextHelper, holder.getContext());
+
+        return holder.getMappings();
+    }
+
+    public synchronized Collection<AbstractMapping> removeHttpContext(HttpContext context)
+    {
+        String id = this.contextMap.remove(context);
+        if (id != null)
+        {
+            HttpContextHolder holder = this.idMap.remove(id);
+            if (holder != null)
+            {
+                Set<AbstractMapping> mappings = holder.getMappings();
+                if (mappings != null && !mappings.isEmpty())
+                {
+                    // keep the orphans around
+                    final String contextId = getContextId(id);
+                    Set<AbstractMapping> orphans = this.orphanMappings.get(contextId);
+                    if (orphans == null)
+                    {
+                        orphans = new HashSet<AbstractMapping>();
+                        this.orphanMappings.put(getContextId(id), orphans);
+                    }
+
+                    for (AbstractMapping mapping : mappings)
+                    {
+                        mapping.setContext(null);
+                        orphans.add(mapping);
+                    }
+                }
+                return mappings;
+            }
+        }
+        return null;
+    }
+
+    public synchronized Collection<AbstractMapping> removeContextHelper(ServletContextHelper contextHelper)
+    {
+        HttpContext context = this.helperMap.remove(contextHelper);
+        if (context != null)
+        {
+            return removeHttpContext(context);
+        }
+        return null;
+    }
+
+    synchronized Map<String, HttpContextHolder> getHttpContexts()
+    {
+        return new HashMap<String, HttpContextHolder>(this.idMap);
+    }
+
+    synchronized Map<String, Set<AbstractMapping>> getOrphanMappings()
+    {
+        return new HashMap<String, Set<AbstractMapping>>(this.orphanMappings);
+    }
+
+    static class HttpContextHolder
+    {
+        private final HttpContext context;
+        private final Set<AbstractMapping> mappings;
+        private final String path;
+
+        HttpContextHolder(final HttpContext context)
+        {
+            this.context = context;
+            this.mappings = new HashSet<AbstractMapping>();
+            this.path = null;
+        }
+
+        HttpContextHolder(final ServletContextHelper context,
+                          final String path)
+        {
+            this.context = new HttpContextBridge(context);
+            this.mappings = new HashSet<AbstractMapping>();
+            this.path = path;
+        }
+
+        public HttpContext getContext()
+        {
+            return context;
+        }
+
+        public String getPath()
+        {
+            return path;
+        }
+
+        void addMapping(AbstractMapping mapping)
+        {
+            this.mappings.add(mapping);
+            mapping.setContext(getContext());
+        }
+
+        void removeMapping(AbstractMapping mapping)
+        {
+            mapping.setContext(null);
+            this.mappings.remove(mapping);
+        }
+
+        public Set<AbstractMapping> getMappings()
+        {
+            return mappings;
+        }
+    }
+}

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

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

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

Added: felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ResourceMapping.java
URL: http://svn.apache.org/viewvc/felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ResourceMapping.java?rev=1655577&view=auto
==============================================================================
--- felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ResourceMapping.java (added)
+++ felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ResourceMapping.java Thu Jan 29 10:22:38 2015
@@ -0,0 +1,59 @@
+/*
+ * 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.framework.Bundle;
+import org.osgi.service.http.HttpService;
+import org.osgi.service.http.NamespaceException;
+import org.osgi.service.http.runtime.dto.ResourceDTO;
+
+public final class ResourceMapping extends AbstractMapping
+{
+    private final ResourceDTO dto;
+
+    public ResourceMapping(final Bundle bundle, final ResourceDTO resourceDTO)
+    {
+        super(bundle);
+        this.dto = resourceDTO;
+    }
+
+    @Override
+    public void register(final HttpService httpService)
+    {
+        if (!isRegistered() && getContext() != null)
+        {
+            try {
+                httpService.registerResources(this.dto.patterns[0], this.dto.prefix, this.getContext());
+                this.setRegistered(true);
+            }
+            catch (final NamespaceException e)
+            {
+                // TODO Handle exception
+                e.printStackTrace();
+            }
+        }
+    }
+
+    @Override
+    public void unregister(final HttpService httpService)
+    {
+        if (isRegistered())
+        {
+            httpService.unregister(this.dto.patterns[0]);
+        }
+    }
+}

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

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

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

Added: felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletMapping.java
URL: http://svn.apache.org/viewvc/felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletMapping.java?rev=1655577&view=auto
==============================================================================
--- felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletMapping.java (added)
+++ felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletMapping.java Thu Jan 29 10:22:38 2015
@@ -0,0 +1,85 @@
+/*
+ * 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 javax.servlet.Servlet;
+
+import org.apache.felix.http.base.internal.logger.SystemLogger;
+import org.apache.felix.http.base.internal.runtime.ServletInfo;
+import org.apache.felix.http.base.internal.service.HttpServiceImpl;
+import org.osgi.framework.Bundle;
+import org.osgi.service.http.HttpService;
+
+public final class ServletMapping extends AbstractMapping
+{
+    private final Servlet servlet;
+    private final ServletInfo servletInfo;
+
+    public ServletMapping(Bundle bundle, Servlet servlet, ServletInfo servletInfo)
+    {
+        super(bundle);
+        this.servlet = servlet;
+        this.servletInfo = servletInfo;
+    }
+
+    @Override
+    public void register(HttpService httpService)
+    {
+        if (!isRegistered() && (httpService instanceof HttpServiceImpl) && getContext() != null)
+        {
+            this.servletInfo.context = getContext(); // XXX
+            try
+            {
+                ((HttpServiceImpl) httpService).registerServlet(this.servlet, this.servletInfo);
+                setRegistered(true);
+            }
+            catch (Exception e)
+            {
+                // Warn that something might have gone astray...
+                SystemLogger.warning("Failed to register servlet for " + this.servletInfo.name, e);
+            }
+            setRegistered(true);
+        }
+    }
+
+    @Override
+    public void unregister(HttpService httpService)
+    {
+        if (isRegistered() && (httpService instanceof HttpServiceImpl))
+        {
+            try
+            {
+                ((HttpServiceImpl) httpService).unregisterServlet(this.servlet);
+            }
+            catch (Exception e)
+            {
+                // Warn that something might have gone astray...
+                SystemLogger.debug("Failed to unregister servlet for " + this.servletInfo.name, e);
+            }
+            finally
+            {
+                // Best effort: avoid mappings that are registered which is reality aren't registered...
+                setRegistered(false);
+            }
+        }
+    }
+
+    Servlet getServlet()
+    {
+        return this.servlet;
+    }
+}

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

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

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

Added: felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/AbstractTracker.java
URL: http://svn.apache.org/viewvc/felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/AbstractTracker.java?rev=1655577&view=auto
==============================================================================
--- felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/AbstractTracker.java (added)
+++ felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/AbstractTracker.java Thu Jan 29 10:22:38 2015
@@ -0,0 +1,65 @@
+/*
+ * 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 org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+
+public abstract class AbstractTracker<T> extends ServiceTracker
+{
+    public AbstractTracker(final BundleContext context, final Class<T> clz)
+    {
+        super(context, clz.getName(), null);
+    }
+
+    public AbstractTracker(final BundleContext context, final Filter filter)
+    {
+        super(context, filter, null);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public final Object addingService(final ServiceReference ref)
+    {
+        T service = (T) super.addingService(ref);
+        added(service, ref);
+        return service;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public final void modifiedService(final ServiceReference ref, final Object service)
+    {
+        modified( (T)service, ref);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public final void removedService(final ServiceReference ref, final Object service)
+    {
+        super.removedService(ref, service);
+        removed((T) service, ref);
+    }
+
+    protected abstract void modified(T service, ServiceReference ref);
+
+    protected abstract void added(T service, ServiceReference ref);
+
+    protected abstract void removed(T service, ServiceReference ref);
+}

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

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

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

Added: felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/FilterTracker.java
URL: http://svn.apache.org/viewvc/felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/FilterTracker.java?rev=1655577&view=auto
==============================================================================
--- felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/FilterTracker.java (added)
+++ felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/FilterTracker.java Thu Jan 29 10:22:38 2015
@@ -0,0 +1,72 @@
+/*
+ * 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.Filter;
+
+import org.apache.felix.http.base.internal.whiteboard.ExtenderManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
+
+public final class FilterTracker extends AbstractTracker<Filter>
+{
+    private final ExtenderManager manager;
+
+    private static org.osgi.framework.Filter createFilter(final BundleContext btx)
+    {
+        try
+        {
+            return btx.createFilter(String.format("(&(objectClass=%s)(|(%s=*)(%s=*)(%s=*)))",
+                    Filter.class.getName(),
+                    HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN,
+                    HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_REGEX,
+                    HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_SERVLET));
+        }
+        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 FilterTracker(BundleContext context, ExtenderManager manager)
+    {
+        super(context, createFilter(context));
+        this.manager = manager;
+    }
+
+    @Override
+    protected void added(Filter service, ServiceReference ref)
+    {
+        this.manager.add(service, ref);
+    }
+
+    @Override
+    protected void modified(Filter service, ServiceReference ref)
+    {
+        removed(service, ref);
+        added(service, ref);
+    }
+
+    @Override
+    protected void removed(Filter service, ServiceReference ref)
+    {
+        this.manager.removeFilter(ref);
+    }
+}

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

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

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

Added: felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ResourceTracker.java
URL: http://svn.apache.org/viewvc/felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ResourceTracker.java?rev=1655577&view=auto
==============================================================================
--- felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ResourceTracker.java (added)
+++ felix/sandbox/http-rfc189/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/ResourceTracker.java Thu Jan 29 10:22:38 2015
@@ -0,0 +1,69 @@
+/*
+ * 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 org.apache.felix.http.base.internal.whiteboard.ExtenderManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
+
+public final class ResourceTracker extends AbstractTracker<Object>
+{
+    private final ExtenderManager manager;
+
+    private static Filter createFilter(final BundleContext btx)
+    {
+        try
+        {
+            return btx.createFilter(String.format("(&(%s=*)(%s=*))",
+                    HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN,
+                    HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX));
+        }
+        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 ResourceTracker(final BundleContext context, final ExtenderManager manager)
+    {
+        super(context, createFilter(context));
+        this.manager = manager;
+    }
+
+    @Override
+    protected void added(final Object service, final ServiceReference ref)
+    {
+        this.manager.addResource(ref);
+    }
+
+    @Override
+    protected void modified(final Object service, final ServiceReference ref)
+    {
+        removed(service, ref);
+        added(service, ref);
+    }
+
+    @Override
+    protected void removed(final Object service, final ServiceReference ref)
+    {
+        this.manager.removeResource(ref);
+    }
+}