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/05/16 19:08:17 UTC

svn commit: r1679748 - in /felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal: handler/ handler/holder/ registry/

Author: cziegeler
Date: Sat May 16 17:08:16 2015
New Revision: 1679748

URL: http://svn.apache.org/r1679748
Log:
FELIX-4888 : ServletHandler's are not sorted by longest matching path. Start new registry implementation

Added:
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PathResolution.java   (with props)
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java   (with props)
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletHandler.java   (with props)
Removed:
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/holder/AbstractHolder.java
Modified:
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ErrorsMapping.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerMapping.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRankingMultimap.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/holder/ServletHolder.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/holder/WhiteboardServletHolder.java

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ErrorsMapping.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ErrorsMapping.java?rev=1679748&r1=1679747&r2=1679748&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ErrorsMapping.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ErrorsMapping.java Sat May 16 17:08:16 2015
@@ -32,18 +32,18 @@ public final class ErrorsMapping
     private final Map<Integer, ServletHandler> errorCodesMap;
     private final Map<String, ServletHandler> exceptionsMap;
 
-    ErrorsMapping()
+    public ErrorsMapping()
     {
         this(new HashMap<Integer, ServletHandler>(), new HashMap<String, ServletHandler>());
     }
 
-    ErrorsMapping(Map<Integer, ServletHandler> errorCodesMap, Map<String, ServletHandler> exceptionsMap)
+    public ErrorsMapping(Map<Integer, ServletHandler> errorCodesMap, Map<String, ServletHandler> exceptionsMap)
     {
         this.errorCodesMap = errorCodesMap;
         this.exceptionsMap = exceptionsMap;
     }
 
-    ErrorsMapping update(Map<String, ServletHandler> add, Map<String, ServletHandler> remove) throws RegistrationFailureException
+    public ErrorsMapping update(Map<String, ServletHandler> add, Map<String, ServletHandler> remove) throws RegistrationFailureException
     {
         Map<Integer, ServletHandler> newErrorCodesMap = new HashMap<Integer, ServletHandler>(this.errorCodesMap);
         Map<String, ServletHandler> newExceptionsMap = new HashMap<String, ServletHandler>(this.exceptionsMap);;
@@ -160,7 +160,7 @@ public final class ErrorsMapping
 
 
     @SuppressWarnings("unchecked")
-    Collection<ServletHandler> values()
+    public Collection<ServletHandler> values()
     {
         return sortedUnion(errorCodesMap.values(), exceptionsMap.values());
     }

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerMapping.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerMapping.java?rev=1679748&r1=1679747&r2=1679748&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerMapping.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerMapping.java Sat May 16 17:08:16 2015
@@ -42,10 +42,10 @@ import org.apache.felix.http.base.intern
  * 3.0 specification.
  * <p>
  * {@link HandlerMapping} instances are immutable.
- * 
+ *
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-final class HandlerMapping<V extends AbstractHandler<V>>
+public final class HandlerMapping<V extends AbstractHandler<V>>
 {
     private final SortedMap<Pattern, Set<V>> exactMap;
     private final SortedMap<Pattern, Set<V>> wildcardMap;
@@ -54,7 +54,7 @@ final class HandlerMapping<V extends Abs
     /**
      * Creates a new, empty, {@link HandlerMapping} instance.
      */
-    HandlerMapping()
+    public HandlerMapping()
     {
         this(Collections.<Pattern, Collection<V>>emptyMap());
     }
@@ -108,7 +108,7 @@ final class HandlerMapping<V extends Abs
      * @return a new {@link HandlerMapping} instance with a mapping for the
      *         given handler.
      */
-    HandlerMapping<V> add(V handler)
+    public HandlerMapping<V> add(V handler)
     {
         Map<Pattern, V> mappings = new TreeMap<Pattern, V>(PatternComparator.INSTANCE);
         for (Pattern pattern : handler.getPatterns())
@@ -133,7 +133,7 @@ final class HandlerMapping<V extends Abs
      * @return a new {@link HandlerMapping} instance without a mapping for the
      *         given handler.
      */
-    HandlerMapping<V> remove(V handler)
+    public HandlerMapping<V> remove(V handler)
     {
         Map<Pattern, V> mappings = new TreeMap<Pattern, V>(PatternComparator.INSTANCE);
         for (Pattern pattern : handler.getPatterns())
@@ -197,23 +197,23 @@ final class HandlerMapping<V extends Abs
 
     /**
      * Returns all mapped handlers.
-     * 
+     *
      * @return the handlers contained in this mapping. The returned
      *         <code>Collection</code> is unmodifiable and never
      *         <code>null</code>.
      */
-    Collection<V> values()
+    public Collection<V> values()
     {
         return unmodifiableCollection(mappedHandlers);
     }
 
     /**
      * Returns whether this mapping contains the specified handler.
-     * 
+     *
      * @return <code>true</code> if the handlers contains the specified handler,
      *         <code>false</code> otherwise
      */
-    boolean contains(V handler)
+    public boolean contains(V handler)
     {
         return mappedHandlers.contains(handler);
     }
@@ -224,7 +224,7 @@ final class HandlerMapping<V extends Abs
      * @param path the path that should match, cannot be <code>null</code>.
      * @return a {@link Collection} of all matching handlers, never <code>null</code>.
      */
-    List<V> getAllMatches(String path)
+    public List<V> getAllMatches(String path)
     {
         return getAllMatches(path, false /* firstOnly */);
     }

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRankingMultimap.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRankingMultimap.java?rev=1679748&r1=1679747&r2=1679748&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRankingMultimap.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRankingMultimap.java Sat May 16 17:08:16 2015
@@ -32,7 +32,7 @@ import java.util.TreeMap;
 import java.util.TreeSet;
 
 
-final class HandlerRankingMultimap<K>
+public final class HandlerRankingMultimap<K>
 {
     private final Map<ServletHandler, Integer> useCounts = new TreeMap<ServletHandler, Integer>();
 
@@ -42,19 +42,19 @@ final class HandlerRankingMultimap<K>
 
     private int size = 0;
 
-    HandlerRankingMultimap()
+    public HandlerRankingMultimap()
     {
         this.handlerMultimap = new HashMap<K, PriorityQueue<ServletHandler>>();
         this.keyComparator = null;
         this.handlerComparator = null;
     }
 
-    HandlerRankingMultimap(Comparator<K> keyComparator)
+    public HandlerRankingMultimap(Comparator<K> keyComparator)
     {
         this(keyComparator, null);
     }
 
-    HandlerRankingMultimap(Comparator<K> keyComparator, Comparator<ServletHandler> handlerComparator)
+    public HandlerRankingMultimap(Comparator<K> keyComparator, Comparator<ServletHandler> handlerComparator)
     {
         this.keyComparator = keyComparator;
         this.handlerMultimap = new TreeMap<K, PriorityQueue<ServletHandler>>(keyComparator);
@@ -66,7 +66,7 @@ final class HandlerRankingMultimap<K>
         return useCounts.containsKey(handler);
     }
 
-    Update<K> add(K[] keys, ServletHandler handler)
+    public Update<K> add(K[] keys, ServletHandler handler)
     {
         return add(asList(keys), handler);
     }
@@ -103,7 +103,7 @@ final class HandlerRankingMultimap<K>
         return Update.forAdd(activate, deactivate, destroy);
     }
 
-    Update<K> remove(K[] keys, ServletHandler handler)
+    public Update<K> remove(K[] keys, ServletHandler handler)
     {
         return remove(asList(keys), handler);
     }
@@ -199,13 +199,13 @@ final class HandlerRankingMultimap<K>
         return newCount;
     }
 
-    void clear()
+    public void clear()
     {
         handlerMultimap.clear();
         useCounts.clear();
     }
 
-    Collection<ServletHandler> getActiveValues()
+    public Collection<ServletHandler> getActiveValues()
     {
         TreeSet<ServletHandler> activeValues = new TreeSet<ServletHandler>();
         for (PriorityQueue<ServletHandler> queue : handlerMultimap.values())
@@ -215,7 +215,7 @@ final class HandlerRankingMultimap<K>
         return activeValues;
     }
 
-    Collection<ServletHandler> getShadowedValues()
+    public Collection<ServletHandler> getShadowedValues()
     {
         TreeSet<ServletHandler> shadowedValues = new TreeSet<ServletHandler>();
         for (PriorityQueue<ServletHandler> queue : handlerMultimap.values())
@@ -251,7 +251,7 @@ final class HandlerRankingMultimap<K>
         return keyComparator == null ? new HashMap<K, ServletHandler>() : new TreeMap<K, ServletHandler>(keyComparator);
     }
 
-    static final class Update<K>
+    public static final class Update<K>
     {
         private final Map<K, ServletHandler> activate;
         private final Map<K, ServletHandler> deactivate;
@@ -299,22 +299,22 @@ final class HandlerRankingMultimap<K>
             return valueSet;
         }
 
-        Map<K, ServletHandler> getActivated()
+        public Map<K, ServletHandler> getActivated()
         {
             return activate;
         }
 
-        Map<K, ServletHandler> getDeactivated()
+        public Map<K, ServletHandler> getDeactivated()
         {
             return deactivate;
         }
 
-        Collection<ServletHandler> getInit()
+        public Collection<ServletHandler> getInit()
         {
             return init;
         }
 
-        Collection<ServletHandler> getDestroy()
+        public Collection<ServletHandler> getDestroy()
         {
             return destroy;
         }

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/holder/ServletHolder.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/holder/ServletHolder.java?rev=1679748&r1=1679747&r2=1679748&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/holder/ServletHolder.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/holder/ServletHolder.java Sat May 16 17:08:16 2015
@@ -32,20 +32,34 @@ import org.osgi.service.http.runtime.dto
 /**
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-public abstract class ServletHolder extends AbstractHolder<ServletHolder>
+public abstract class ServletHolder implements Comparable<ServletHolder>
 {
     private final ServletInfo servletInfo;
 
+    private final ServletContext context;
+
     private volatile Servlet servlet;
 
+    protected volatile int useCount;
+
     public ServletHolder(final ServletContext context,
             final ServletInfo servletInfo)
     {
-        super(context);
-
+        this.context = context;
         this.servletInfo = servletInfo;
     }
 
+    @Override
+    public int compareTo(final ServletHolder other)
+    {
+        return this.servletInfo.compareTo(other.servletInfo);
+    }
+
+    protected ServletContext getContext()
+    {
+        return this.context;
+    }
+
     protected Servlet getServlet()
     {
         return servlet;
@@ -56,19 +70,13 @@ public abstract class ServletHolder exte
         this.servlet = s;
     }
 
-    @Override
-    public int compareTo(final ServletHolder other)
-    {
-        return this.servletInfo.compareTo(other.servletInfo);
-    }
-
     public void handle(final ServletRequest req, final ServletResponse res)
             throws ServletException, IOException
     {
         this.servlet.service(req, res);
     }
 
-    protected ServletInfo getServletInfo()
+    public ServletInfo getServletInfo()
     {
         return this.servletInfo;
     }
@@ -83,42 +91,63 @@ public abstract class ServletHolder exte
         return name;
     }
 
-    @Override
+    /**
+     * Initialize the object
+     * @return {code -1} on success, a failure reason according to {@link DTOConstants} otherwise.
+     */
     public int init()
     {
+        if ( this.useCount > 0 )
+        {
+            return -1;
+        }
+
         if (this.servlet == null)
         {
             return DTOConstants.FAILURE_REASON_SERVICE_NOT_GETTABLE;
         }
 
-        try {
+        try
+        {
             servlet.init(new ServletConfigImpl(getName(), getContext(), getServletInfo().getInitParameters()));
-        } catch (final ServletException e) {
+        }
+        catch (final ServletException e)
+        {
             SystemLogger.error(this.getServletInfo().getServiceReference(),
                     "Error during calling init() on servlet " + this.servlet,
                     e);
             return DTOConstants.FAILURE_REASON_EXCEPTION_ON_INIT;
         }
+        this.useCount++;
         return -1;
     }
 
-    @Override
-    public void destroy()
+
+    public boolean destroy()
     {
         if (this.servlet == null)
         {
-            return;
+            return false;
         }
 
-        try {
-            servlet.destroy();
-        } catch ( final Exception ignore ) {
-            // we ignore this
-            SystemLogger.error(this.getServletInfo().getServiceReference(),
-                    "Error during calling destroy() on servlet " + this.servlet,
-                    ignore);
-        }
+        this.useCount--;
+        if ( this.useCount == 0 )
+        {
+            try
+            {
+                servlet.destroy();
+            }
+            catch ( final Exception ignore )
+            {
+                // we ignore this
+                SystemLogger.error(this.getServletInfo().getServiceReference(),
+                        "Error during calling destroy() on servlet " + this.servlet,
+                        ignore);
+            }
 
-        servlet = null;
+            servlet = null;
+            return true;
+        }
+        return false;
     }
 }

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/holder/WhiteboardServletHolder.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/holder/WhiteboardServletHolder.java?rev=1679748&r1=1679747&r2=1679748&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/holder/WhiteboardServletHolder.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/holder/WhiteboardServletHolder.java Sat May 16 17:08:16 2015
@@ -42,6 +42,11 @@ public final class WhiteboardServletHold
     @Override
     public int init()
     {
+        if ( this.useCount > 0 )
+        {
+            return -1;
+        }
+
         final ServiceReference<Servlet> serviceReference = getServletInfo().getServiceReference();
         final ServiceObjects<Servlet> so = this.bundleContext.getServiceObjects(serviceReference);
 
@@ -57,18 +62,22 @@ public final class WhiteboardServletHold
     }
 
     @Override
-    public void destroy()
+    public boolean destroy()
     {
         final Servlet s = this.getServlet();
         if ( s != null )
         {
-            super.destroy();
-
-            final ServiceObjects<Servlet> so = this.bundleContext.getServiceObjects(getServletInfo().getServiceReference());
-            if (so != null)
+            if ( super.destroy() )
             {
-                so.ungetService(s);
+
+                final ServiceObjects<Servlet> so = this.bundleContext.getServiceObjects(getServletInfo().getServiceReference());
+                if (so != null)
+                {
+                    so.ungetService(s);
+                }
+                return true;
             }
         }
+        return false;
     }
 }

Added: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PathResolution.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PathResolution.java?rev=1679748&view=auto
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PathResolution.java (added)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PathResolution.java Sat May 16 17:08:16 2015
@@ -0,0 +1,28 @@
+/*
+ * 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.registry;
+
+import org.apache.felix.http.base.internal.handler.holder.ServletHolder;
+
+public class PathResolution {
+
+    public String servletPath;
+
+    public String pathInfo;
+
+    public ServletHolder holder;
+}

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

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

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

Added: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java?rev=1679748&view=auto
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java (added)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/PerContextHandlerRegistry.java Sat May 16 17:08:16 2015
@@ -0,0 +1,216 @@
+/*
+ * 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.registry;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Pattern;
+
+import javax.annotation.Nonnull;
+
+import org.apache.felix.http.base.internal.handler.holder.ServletHolder;
+import org.apache.felix.http.base.internal.runtime.ServletContextHelperInfo;
+import org.apache.felix.http.base.internal.util.PatternUtil;
+
+/**
+ * This registry keeps track of all processing components per context:
+ * - servlets
+ * - filters
+ * - error pages
+ */
+public final class PerContextHandlerRegistry implements Comparable<PerContextHandlerRegistry>
+{
+    /** Service id of the context. */
+    private final long serviceId;
+
+    /** Ranking of the context. */
+    private final int ranking;
+
+    /** The context path. */
+    private final String path;
+
+    /** The context prefix. */
+    private final String prefix;
+
+    private Map<String, ServletHandler> activateServletMappings = new ConcurrentHashMap<String, ServletHandler>();
+
+    private Map<String, List<ServletHolder>> inactivateServletMappings = new HashMap<String, List<ServletHolder>>();
+
+    /**
+     * Default http service registry
+     */
+    public PerContextHandlerRegistry()
+    {
+        this.serviceId = 0;
+        this.ranking = Integer.MAX_VALUE;
+        this.path = "/";
+        this.prefix = null;
+    }
+
+    /**
+     * Registry for a servlet context helper (whiteboard support)
+     * @param info The servlet context helper info
+     */
+    public PerContextHandlerRegistry(@Nonnull final ServletContextHelperInfo info)
+    {
+        this.serviceId = info.getServiceId();
+        this.ranking = info.getRanking();
+        this.path = info.getPath();
+        if ( this.path.equals("/") )
+        {
+            this.prefix = null;
+        }
+        else
+        {
+            this.prefix = this.path + "/";
+        }
+    }
+
+    @Override
+    public int compareTo(@Nonnull final PerContextHandlerRegistry other)
+    {
+        // the context of the HttpService is the least element
+        if (this.serviceId == 0 ^ other.serviceId == 0)
+        {
+            return this.serviceId == 0 ? -1 : 1;
+        }
+
+        final int result = Integer.compare(other.path.length(), this.path.length());
+        if ( result == 0 ) {
+            if (this.ranking == other.ranking)
+            {
+                // Service id's can be negative. Negative id's follow the reverse natural ordering of integers.
+                int reverseOrder = ( this.serviceId <= 0 && other.serviceId <= 0 ) ? -1 : 1;
+                return reverseOrder * Long.compare(this.serviceId, other.serviceId);
+            }
+
+            return Integer.compare(other.ranking, this.ranking);
+        }
+        return result;
+    }
+
+    public String isMatching(final String requestURI)
+    {
+        if (requestURI.equals(this.path))
+        {
+            return "";
+        }
+        if (this.prefix == null)
+        {
+            return requestURI;
+        }
+        if (requestURI.startsWith(this.prefix))
+        {
+            return requestURI.substring(this.prefix.length() - 1);
+        }
+        return null;
+    }
+
+    public PathResolution resolve(final String relativeRequestURI)
+    {
+        int len = -1;
+        PathResolution candidate = null;
+        for(final Map.Entry<String, ServletHandler> entry : this.activateServletMappings.entrySet())
+        {
+            final PathResolution pr = entry.getValue().resolve(relativeRequestURI);
+            if ( pr != null && entry.getKey().length() > len )
+            {
+                candidate = pr;
+                len = entry.getKey().length();
+            }
+        }
+        return candidate;
+    }
+
+    /**
+     * Add a servlet
+     * @param holder The servlet holder
+     * @param info The servlet info
+     */
+    public void addServlet(@Nonnull final ServletHolder holder)
+    {
+        // we have to check for every pattern in the info
+        // Can be null in case of error-handling servlets...
+        final String[] patternStrings = holder.getServletInfo().getPatterns();
+        if ( patternStrings != null )
+        {
+            final int length = patternStrings.length;
+            for (int i = 0; i < length; i++)
+            {
+                final String pattern = patternStrings[i];
+
+                final ServletHandler regHandler = this.activateServletMappings.get(pattern);
+                if ( regHandler != null )
+                {
+                    if ( regHandler.getServletHolder().getServletInfo().getServiceReference().compareTo(holder.getServletInfo().getServiceReference()) < 0 )
+                    {
+                        // replace if no error with new servlet
+                        if ( holder.init() == -1 )
+                        {
+                            final Pattern p = Pattern.compile(PatternUtil.convertToRegEx(pattern));
+                            final ServletHandler handler = new ServletHandler(holder, p);
+                            this.activateServletMappings.put(pattern, handler);
+
+                            regHandler.getServletHolder().destroy();
+
+                            this.addToInactiveList(pattern, regHandler.getServletHolder());
+                        }
+                        else
+                        {
+                            // TODO - add to failure
+                        }
+                    }
+                    else
+                    {
+                        // add to inactive
+                        this.addToInactiveList(pattern, holder);
+                    }
+                }
+                else
+                {
+                    // add to active
+                    if ( holder.init() == -1 )
+                    {
+                        final Pattern p = Pattern.compile(PatternUtil.convertToRegEx(pattern));
+                        final ServletHandler handler = new ServletHandler(holder, p);
+                        this.activateServletMappings.put(pattern, handler);
+                    }
+                    else
+                    {
+                        // TODO - add to failure
+                    }
+                }
+            }
+        }
+    }
+
+    private void addToInactiveList(final String pattern, final ServletHolder holder)
+    {
+        List<ServletHolder> inactiveList = this.inactivateServletMappings.get(pattern);
+        if ( inactiveList == null )
+        {
+            inactiveList = new ArrayList<ServletHolder>(inactiveList);
+            this.inactivateServletMappings.put(pattern, inactiveList);
+        }
+        inactiveList.add(holder);
+        Collections.sort(inactiveList);
+    }
+}

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

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

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

Added: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletHandler.java?rev=1679748&view=auto
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletHandler.java (added)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/registry/ServletHandler.java Sat May 16 17:08:16 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.registry;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.annotation.Nonnull;
+
+import org.apache.felix.http.base.internal.handler.holder.ServletHolder;
+import org.apache.felix.http.base.internal.util.UriUtils;
+
+/**
+ * Servlet handler is registered with a pattern and a servlet holder
+ */
+public class ServletHandler
+{
+    private final ServletHolder holder;
+    private final Pattern pattern;
+
+    public ServletHandler(@Nonnull final ServletHolder holder, @Nonnull final Pattern pattern)
+    {
+        this.holder = holder;
+        this.pattern = pattern;
+    }
+
+    public ServletHolder getServletHolder()
+    {
+        return this.holder;
+    }
+
+    public PathResolution resolve(@Nonnull final String requestURI)
+    {
+        final Matcher matcher = pattern.matcher(requestURI);
+        if (matcher.find(0))
+        {
+            final PathResolution pr = new PathResolution();
+            pr.servletPath = matcher.groupCount() > 0 ? matcher.group(1) : matcher.group();
+            pr.pathInfo = UriUtils.compactPath(UriUtils.relativePath(pr.servletPath, requestURI));
+            pr.holder = this.holder;
+        }
+
+        return null;
+    }
+}

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

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

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