felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cziege...@apache.org
Subject svn commit: r1656064 [1/2] - in /felix/trunk/http/base/src: main/java/org/apache/felix/http/base/internal/dispatch/ main/java/org/apache/felix/http/base/internal/handler/ main/java/org/apache/felix/http/base/internal/runtime/ main/java/org/apache/felix...
Date Fri, 30 Jan 2015 17:22:32 GMT
Author: cziegeler
Date: Fri Jan 30 17:22:31 2015
New Revision: 1656064

URL: http://svn.apache.org/r1656064
Log:
FELIX-4545 : Implement Servlet Context Helper. Merge new path handling from branch

Added:
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletContextWrapper.java
      - copied, changed from r1655297, felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletContextWrapper.java
Removed:
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/FilterPipeline.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletPipeline.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletContextWrapper.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandlerRequest.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/DefaultHttpContext.java
    felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/handler/ServletHandlerRequestTest.java
Modified:
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/HttpFilterChain.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/InvocationFilterChain.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/NotFoundFilterChain.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/AbstractHandler.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpServicePlugin.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/AbstractInfo.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ContextInfo.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/FilterInfo.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/util/UriUtils.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ExtenderManager.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/ServletContextHelperManager.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/tracker/FilterTracker.java
    felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/handler/AbstractHandlerTest.java
    felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/handler/FilterHandlerTest.java
    felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/handler/HandlerRegistryTest.java
    felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/handler/ServletHandlerTest.java
    felix/trunk/http/base/src/test/java/org/apache/felix/http/base/internal/util/UriUtilsTest.java

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java?rev=1656064&r1=1656063&r2=1656064&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java Fri Jan 30 17:22:31 2015
@@ -16,19 +16,374 @@
  */
 package org.apache.felix.http.base.internal.dispatch;
 
+import static javax.servlet.RequestDispatcher.FORWARD_CONTEXT_PATH;
+import static javax.servlet.RequestDispatcher.FORWARD_PATH_INFO;
+import static javax.servlet.RequestDispatcher.FORWARD_QUERY_STRING;
+import static javax.servlet.RequestDispatcher.FORWARD_REQUEST_URI;
+import static javax.servlet.RequestDispatcher.FORWARD_SERVLET_PATH;
+import static javax.servlet.RequestDispatcher.INCLUDE_CONTEXT_PATH;
+import static javax.servlet.RequestDispatcher.INCLUDE_PATH_INFO;
+import static javax.servlet.RequestDispatcher.INCLUDE_QUERY_STRING;
+import static javax.servlet.RequestDispatcher.INCLUDE_REQUEST_URI;
+import static javax.servlet.RequestDispatcher.INCLUDE_SERVLET_PATH;
+import static org.apache.felix.http.base.internal.util.UriUtils.concat;
+import static org.apache.felix.http.base.internal.util.UriUtils.decodePath;
+import static org.apache.felix.http.base.internal.util.UriUtils.removeDotSegments;
+
 import java.io.IOException;
 
+import javax.servlet.DispatcherType;
 import javax.servlet.FilterChain;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
 import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
 
+import org.apache.felix.http.base.internal.context.ExtServletContext;
+import org.apache.felix.http.base.internal.handler.ErrorsMapping;
+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.HttpSessionWrapper;
+import org.apache.felix.http.base.internal.handler.ServletHandler;
+import org.apache.felix.http.base.internal.util.UriUtils;
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.useradmin.Authorization;
 
-public final class Dispatcher
+public final class Dispatcher implements RequestDispatcherProvider
 {
+    /**
+     * Wrapper implementation for {@link RequestDispatcher}.
+     */
+    final class RequestDispatcherImpl implements RequestDispatcher
+    {
+        private final RequestInfo requestInfo;
+        private final ServletHandler handler;
+
+        public RequestDispatcherImpl(ServletHandler handler, RequestInfo requestInfo)
+        {
+            this.handler = handler;
+            this.requestInfo = requestInfo;
+        }
+
+        @Override
+        public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException
+        {
+            if (response.isCommitted())
+            {
+                throw new ServletException("Response has been committed");
+            }
+            else
+            {
+                // See section 9.4 of Servlet 3.0 spec
+                response.resetBuffer();
+            }
+
+            try
+            {
+                ServletRequestWrapper req = new ServletRequestWrapper((HttpServletRequest) request, this.handler.getContext(), this.requestInfo, DispatcherType.FORWARD);
+                Dispatcher.this.forward(this.handler, req, (HttpServletResponse) response);
+            }
+            finally
+            {
+                // After a forward has taken place, the results should be committed,
+                // see section 9.4 of Servlet 3.0 spec...
+                if (!request.isAsyncStarted())
+                {
+                    response.flushBuffer();
+                    response.getWriter().close();
+                }
+            }
+        }
+
+        @Override
+        public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException
+        {
+            ServletRequestWrapper req = new ServletRequestWrapper((HttpServletRequest) request, this.handler.getContext(), this.requestInfo, DispatcherType.INCLUDE);
+            Dispatcher.this.include(this.handler, req, (HttpServletResponse) response);
+        }
+    }
+
+    final class ServletRequestWrapper extends HttpServletRequestWrapper
+    {
+        private final DispatcherType type;
+        private final RequestInfo requestInfo;
+        private final ExtServletContext servletContext;
+
+        public ServletRequestWrapper(HttpServletRequest req, ExtServletContext servletContext, RequestInfo requestInfo)
+        {
+            this(req, servletContext, requestInfo, null /* type */);
+        }
+
+        public ServletRequestWrapper(HttpServletRequest req, ExtServletContext servletContext, RequestInfo requestInfo, DispatcherType type)
+        {
+            super(req);
+
+            this.servletContext = servletContext;
+            this.requestInfo = requestInfo;
+            this.type = type;
+        }
+
+        @Override
+        public Object getAttribute(String name)
+        {
+            HttpServletRequest request = (HttpServletRequest) getRequest();
+            if (isInclusionDispatcher())
+            {
+                // The javax.servlet.include.* attributes refer to the information of the *included* request,
+                // meaning that the request information comes from the *original* request...
+                if (INCLUDE_REQUEST_URI.equals(name))
+                {
+                    return concat(request.getContextPath(), this.requestInfo.requestURI);
+                }
+                else if (INCLUDE_CONTEXT_PATH.equals(name))
+                {
+                    return request.getContextPath();
+                }
+                else if (INCLUDE_SERVLET_PATH.equals(name))
+                {
+                    return this.requestInfo.servletPath;
+                }
+                else if (INCLUDE_PATH_INFO.equals(name))
+                {
+                    return this.requestInfo.pathInfo;
+                }
+                else if (INCLUDE_QUERY_STRING.equals(name))
+                {
+                    return this.requestInfo.queryString;
+                }
+            }
+            else if (isForwardingDispatcher())
+            {
+                // The javax.servlet.forward.* attributes refer to the information of the *original* request,
+                // meaning that the request information comes from the *forwarded* request...
+                if (FORWARD_REQUEST_URI.equals(name))
+                {
+                    return super.getRequestURI();
+                }
+                else if (FORWARD_CONTEXT_PATH.equals(name))
+                {
+                    return request.getContextPath();
+                }
+                else if (FORWARD_SERVLET_PATH.equals(name))
+                {
+                    return super.getServletPath();
+                }
+                else if (FORWARD_PATH_INFO.equals(name))
+                {
+                    return super.getPathInfo();
+                }
+                else if (FORWARD_QUERY_STRING.equals(name))
+                {
+                    return super.getQueryString();
+                }
+            }
+            return super.getAttribute(name);
+        }
+
+        @Override
+        public String getAuthType()
+        {
+            String authType = (String) getAttribute(HttpContext.AUTHENTICATION_TYPE);
+            if (authType == null)
+            {
+                authType = super.getAuthType();
+            }
+            return authType;
+        }
+
+        @Override
+        public String getContextPath()
+        {
+            /*
+             * FELIX-2030 Calculate the context path for the Http Service
+             * registered servlets from the container context and servlet paths
+             */
+            //            if (contextPath == null)
+            //            {
+            //                final String context = super.getContextPath();
+            //                final String servlet = super.getServletPath();
+            //                if (context == null || context.length() == 0)
+            //                {
+            //                    contextPath = servlet;
+            //                }
+            //                else if (servlet == null || servlet.length() == 0)
+            //                {
+            //                    contextPath = context;
+            //                }
+            //                else
+            //                {
+            //                    contextPath = context + servlet;
+            //                }
+            //            }
+
+            return super.getContextPath();
+        }
+
+        @Override
+        public DispatcherType getDispatcherType()
+        {
+            return (this.type == null) ? super.getDispatcherType() : this.type;
+        }
+
+        @Override
+        public String getPathInfo()
+        {
+            String pathInfo = super.getPathInfo();
+            if (isForwardingDispatcher() || !isWrapperFor(ServletRequestWrapper.class))
+            {
+                pathInfo = this.requestInfo.pathInfo;
+            }
+            return pathInfo;
+        }
+
+        @Override
+        @SuppressWarnings("deprecation")
+        public String getPathTranslated()
+        {
+            final String info = getPathInfo();
+            return (null == info) ? null : getRealPath(info);
+        }
+
+        @Override
+        public String getRemoteUser()
+        {
+            String remoteUser = (String) getAttribute(HttpContext.REMOTE_USER);
+            if (remoteUser != null)
+            {
+                return remoteUser;
+            }
+
+            return super.getRemoteUser();
+        }
+
+        @Override
+        public RequestDispatcher getRequestDispatcher(String path)
+        {
+            // See section 9.1 of Servlet 3.0 specification...
+            if (path == null)
+            {
+                return null;
+            }
+            // Handle relative paths, see Servlet 3.0 spec, section 9.1 last paragraph.
+            boolean relPath = !path.startsWith("/") && !"".equals(path);
+            if (relPath)
+            {
+                path = concat(getServletPath(), path);
+            }
+            return Dispatcher.this.getRequestDispatcher(path);
+        }
+
+        @Override
+        public String getRequestURI()
+        {
+            String requestURI = super.getRequestURI();
+            if (isForwardingDispatcher() || !isWrapperFor(ServletRequestWrapper.class))
+            {
+                requestURI = concat(getContextPath(), this.requestInfo.requestURI);
+            }
+            return requestURI;
+        }
+
+        @Override
+        public ServletContext getServletContext()
+        {
+            return new ServletContextWrapper(this.servletContext, Dispatcher.this);
+        }
+
+        @Override
+        public String getServletPath()
+        {
+            String servletPath = super.getServletPath();
+            if (isForwardingDispatcher() || !isWrapperFor(ServletRequestWrapper.class))
+            {
+                servletPath = this.requestInfo.servletPath;
+            }
+            if ("/".equals(servletPath))
+            {
+                return ""; // XXX still necessary?
+            }
+            return servletPath;
+        }
+
+        @Override
+        public HttpSession getSession(boolean create)
+        {
+            // FELIX-2797: wrap the original HttpSession to provide access to the correct ServletContext...
+            HttpSession session = super.getSession(create);
+            if (session == null)
+            {
+                return null;
+            }
+            return new HttpSessionWrapper(session, this.servletContext);
+        }
+
+        @Override
+        public boolean isUserInRole(String role)
+        {
+            Authorization authorization = (Authorization) getAttribute(HttpContext.AUTHORIZATION);
+            if (authorization != null)
+            {
+                return authorization.hasRole(role);
+            }
+
+            return super.isUserInRole(role);
+        }
+
+        @Override
+        public String toString()
+        {
+            return getClass().getSimpleName() + "->" + super.getRequest();
+        }
+
+        private boolean isForwardingDispatcher()
+        {
+            return (DispatcherType.FORWARD == this.type) && (this.requestInfo != null);
+        }
+
+        private boolean isInclusionDispatcher()
+        {
+            return (DispatcherType.INCLUDE == this.type) && (this.requestInfo != null);
+        }
+    }
+
+    private static class RequestInfo
+    {
+        final String servletPath;
+        final String pathInfo;
+        final String queryString;
+        final String requestURI;
+
+        public RequestInfo(String servletPath, String pathInfo, String queryString)
+        {
+            this.servletPath = servletPath;
+            this.pathInfo = pathInfo;
+            this.queryString = queryString;
+            this.requestURI = UriUtils.compactPath(concat(servletPath, pathInfo));
+        }
+
+        @Override
+        public String toString()
+        {
+            StringBuilder sb = new StringBuilder("RequestInfo[servletPath =");
+            sb.append(this.servletPath).append(", pathInfo = ").append(this.pathInfo);
+            sb.append(", queryString = ").append(this.queryString).append("]");
+            return sb.toString();
+        }
+    }
+
+    /**
+     * Request attribute that provides access to the request dispatcher provider.
+     */
     public static final String REQUEST_DISPATCHER_PROVIDER = "org.apache.felix.http.requestDispatcherProvider";
 
+    /**
+     * Catch-all filter chain that simple finishes all requests with a "404 Not Found" error.
+     */
     private static final FilterChain DEFAULT_CHAIN = new NotFoundFilterChain();
 
     private final HandlerRegistry handlerRegistry;
@@ -38,19 +393,145 @@ public final class Dispatcher
         this.handlerRegistry = handlerRegistry;
     }
 
+    /**
+     * Responsible for dispatching a given request to the actual applicable servlet and/or filters in the local registry.
+     *
+     * @param req the {@link ServletRequest} to dispatch;
+     * @param res the {@link ServletResponse} to dispatch.
+     * @throws ServletException in case of exceptions during the actual dispatching;
+     * @throws IOException in case of I/O problems.
+     */
     public void dispatch(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
     {
-        ServletPipeline servletPipeline = new ServletPipeline(this.handlerRegistry.getServlets());
+        String requestURI = getRequestURI(req);
+
+        // Determine which servlets we should forward the request to...
+        ServletHandler servletHandler = this.handlerRegistry.getServletHander(requestURI);
+        FilterHandler[] filterHandlers = this.handlerRegistry.getFilterHandlers(servletHandler, req.getDispatcherType(), requestURI);
+
         // Provides access to the correct request dispatcher...
-        req.setAttribute(REQUEST_DISPATCHER_PROVIDER, servletPipeline);
+        req.setAttribute(REQUEST_DISPATCHER_PROVIDER, this);
+
+        String servletPath = (servletHandler != null) ? servletHandler.determineServletPath(requestURI) : "";
+        String pathInfo = UriUtils.compactPath(UriUtils.relativePath(servletPath, requestURI));
+        String queryString = null; // XXX
+
+        ExtServletContext servletContext = (servletHandler != null) ? servletHandler.getContext() : null;
+        RequestInfo requestInfo = new RequestInfo(servletPath, pathInfo, queryString);
 
         try
         {
-            new FilterPipeline(this.handlerRegistry.getFilters(), servletPipeline).dispatch(req, res, DEFAULT_CHAIN);
+            invokeChain(filterHandlers, servletHandler, new ServletRequestWrapper(req, servletContext, requestInfo), res);
         }
         finally
         {
             req.removeAttribute(REQUEST_DISPATCHER_PROVIDER);
         }
     }
+
+    public boolean handleError(HttpServletRequest request, HttpServletResponse response, int errorCode, String exceptionType) throws IOException
+    {
+        ErrorsMapping errorsMapping = this.handlerRegistry.getErrorsMapping();
+        ServletHandler errorHandler = null;
+
+        if (exceptionType != null)
+        {
+            errorHandler = errorsMapping.get(exceptionType);
+        }
+        else
+        {
+            errorHandler = errorsMapping.get(errorCode);
+        }
+
+        if (errorHandler != null)
+        {
+            // TODO set error attributes! See Servlet 3.0 specification, section 10.9.1...
+            try
+            {
+                return errorHandler.handle(request, response);
+            }
+            catch (ServletException e)
+            {
+                return false; // XXX
+            }
+        }
+
+        return false;
+    }
+
+    @Override
+    public RequestDispatcher getNamedDispatcher(String name)
+    {
+        ServletHandler handler = this.handlerRegistry.getServletHandlerByName(name);
+        return handler != null ? new RequestDispatcherImpl(handler, null) : null;
+    }
+
+    @Override
+    public RequestDispatcher getRequestDispatcher(String path)
+    {
+        // See section 9.1 of Servlet 3.x specification...
+        if (path == null || (!path.startsWith("/") && !"".equals(path)))
+        {
+            return null;
+        }
+
+        String query = null;
+        int q = 0;
+        if ((q = path.indexOf('?')) > 0)
+        {
+            query = path.substring(q + 1);
+            path = path.substring(0, q);
+        }
+        // TODO remove path parameters...
+        String requestURI = decodePath(removeDotSegments(path));
+
+        ServletHandler handler = this.handlerRegistry.getServletHander(requestURI);
+        if (handler == null)
+        {
+            return null;
+        }
+
+        String servletPath = handler.determineServletPath(requestURI);
+        String pathInfo = UriUtils.relativePath(servletPath, path);
+
+        RequestInfo requestInfo = new RequestInfo(servletPath, pathInfo, query);
+        return new RequestDispatcherImpl(handler, requestInfo);
+    }
+
+    /**
+     * @param servletHandler the servlet that should handle the forward request;
+     * @param request the {@link HttpServletRequest};
+     * @param response the {@link HttpServletResponse};
+     */
+    void forward(ServletHandler servletHandler, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+    {
+        String requestURI = getRequestURI(request);
+        FilterHandler[] filterHandlers = this.handlerRegistry.getFilterHandlers(servletHandler, DispatcherType.FORWARD, requestURI);
+
+        invokeChain(filterHandlers, servletHandler, request, response);
+    }
+
+    /**
+     * @param servletHandler the servlet that should handle the include request;
+     * @param request the {@link HttpServletRequest};
+     * @param response the {@link HttpServletResponse};
+     */
+    void include(ServletHandler servletHandler, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+    {
+        String requestURI = getRequestURI(request);
+        FilterHandler[] filterHandlers = this.handlerRegistry.getFilterHandlers(servletHandler, DispatcherType.INCLUDE, requestURI);
+
+        invokeChain(filterHandlers, servletHandler, request, response);
+    }
+
+    private String getRequestURI(HttpServletRequest req)
+    {
+        return UriUtils.relativePath(req.getContextPath(), req.getRequestURI());
+    }
+
+    private void invokeChain(FilterHandler[] filterHandlers, ServletHandler servletHandler, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+    {
+        FilterChain filterChain = new InvocationFilterChain(servletHandler, filterHandlers, DEFAULT_CHAIN);
+        filterChain.doFilter(request, response);
+    }
 }

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/HttpFilterChain.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/HttpFilterChain.java?rev=1656064&r1=1656063&r2=1656064&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/HttpFilterChain.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/HttpFilterChain.java Fri Jan 30 17:22:31 2015
@@ -16,20 +16,28 @@
  */
 package org.apache.felix.http.base.internal.dispatch;
 
+import java.io.IOException;
+
 import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
-import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
 
+/**
+ * Convenience adapter for {@link FilterChain}s that makes the obtrusive casting unnecessary.
+ */
 public abstract class HttpFilterChain implements FilterChain
 {
+    @Override
     public final void doFilter(ServletRequest req, ServletResponse res) throws IOException, ServletException
     {
         doFilter((HttpServletRequest) req, (HttpServletResponse) res);
     }
 
+    /**
+     * @see FilterChain#doFilter(ServletRequest, ServletResponse)
+     */
     protected abstract void doFilter(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException;
 }

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/InvocationFilterChain.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/InvocationFilterChain.java?rev=1656064&r1=1656063&r2=1656064&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/InvocationFilterChain.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/InvocationFilterChain.java Fri Jan 30 17:22:31 2015
@@ -16,41 +16,59 @@
  */
 package org.apache.felix.http.base.internal.dispatch;
 
+import static javax.servlet.http.HttpServletResponse.SC_OK;
+
+import java.io.IOException;
+
 import javax.servlet.FilterChain;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
+
 import org.apache.felix.http.base.internal.handler.FilterHandler;
+import org.apache.felix.http.base.internal.handler.ServletHandler;
 
-public final class InvocationFilterChain extends HttpFilterChain
+class InvocationFilterChain extends HttpFilterChain
 {
-    private final FilterHandler[] handlers;
-    private final ServletPipeline servletPipeline;
-    private final FilterChain proceedingChain;
+    private final ServletHandler servletHandler;
+    private final FilterHandler[] filterHandlers;
+    private final FilterChain defaultChain;
+
     private int index = -1;
 
-    public InvocationFilterChain(FilterHandler[] handlers, ServletPipeline servletPipeline, FilterChain proceedingChain)
+    public InvocationFilterChain(ServletHandler servletHandler, FilterHandler[] filterHandlers, FilterChain defaultChain)
     {
-        this.handlers = handlers;
-        this.servletPipeline = servletPipeline;
-        this.proceedingChain = proceedingChain;
+        this.filterHandlers = filterHandlers;
+        this.servletHandler = servletHandler;
+        this.defaultChain = defaultChain;
     }
 
+    @Override
     protected void doFilter(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException
     {
         this.index++;
 
-        if (this.index < this.handlers.length)
-        {
-            this.handlers[this.index].handle(req, res, this);
-        }
-        else
+        if (this.index < this.filterHandlers.length)
         {
-            if (!this.servletPipeline.handle(req, res))
+            if (this.filterHandlers[this.index].handle(req, res, this))
             {
-                this.proceedingChain.doFilter(req, res);
+                // We're done...
+                return;
             }
         }
+
+        // Last entry in the chain...
+        if (this.servletHandler != null && this.servletHandler.handle(req, res))
+        {
+            // We're done...
+            return;
+        }
+
+        // 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)
+        {
+            this.defaultChain.doFilter(req, res);
+        }
     }
 }

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/NotFoundFilterChain.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/NotFoundFilterChain.java?rev=1656064&r1=1656063&r2=1656064&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/NotFoundFilterChain.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/NotFoundFilterChain.java Fri Jan 30 17:22:31 2015
@@ -16,13 +16,15 @@
  */
 package org.apache.felix.http.base.internal.dispatch;
 
+import java.io.IOException;
+
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
 
 public final class NotFoundFilterChain extends HttpFilterChain
 {
+    @Override
     protected void doFilter(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException
     {
         res.sendError(HttpServletResponse.SC_NOT_FOUND);

Copied: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletContextWrapper.java (from r1655297, felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletContextWrapper.java)
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletContextWrapper.java?p2=felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletContextWrapper.java&p1=felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletContextWrapper.java&r1=1655297&r2=1656064&rev=1656064&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletContextWrapper.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/ServletContextWrapper.java Fri Jan 30 17:22:31 2015
@@ -17,13 +17,12 @@
  * under the License.
  */
 
-package org.apache.felix.http.base.internal.handler;
+package org.apache.felix.http.base.internal.dispatch;
 
 import javax.servlet.RequestDispatcher;
 
 import org.apache.felix.http.base.internal.context.ExtServletContext;
 import org.apache.felix.http.base.internal.context.ServletContextImpl;
-import org.apache.felix.http.base.internal.dispatch.RequestDispatcherProvider;
 
 /**
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/AbstractHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/AbstractHandler.java?rev=1656064&r1=1656063&r2=1656064&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/AbstractHandler.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/AbstractHandler.java Fri Jan 30 17:22:31 2015
@@ -16,11 +16,10 @@
  */
 package org.apache.felix.http.base.internal.handler;
 
-import java.util.Dictionary;
-import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Pattern;
 
 import javax.servlet.Filter;
 import javax.servlet.Servlet;
@@ -28,7 +27,7 @@ import javax.servlet.ServletException;
 
 import org.apache.felix.http.base.internal.context.ExtServletContext;
 
-public abstract class AbstractHandler
+public abstract class AbstractHandler<T extends AbstractHandler> implements Comparable<T>
 {
     private final static AtomicInteger ID = new AtomicInteger();
 
@@ -76,32 +75,7 @@ public abstract class AbstractHandler
 
     public abstract void init() throws ServletException;
 
-    /**
-     * TODO - We can remove this, once we switched to {@link #setInitParams(Map)}
-     * @param map
-     */
-    public final void setInitParams(Dictionary map)
-    {
-        this.initParams.clear();
-        if (map == null)
-        {
-            return;
-        }
-
-        Enumeration e = map.keys();
-        while (e.hasMoreElements())
-        {
-            Object key = e.nextElement();
-            Object value = map.get(key);
-
-            if ((key instanceof String) && (value instanceof String))
-            {
-                this.initParams.put((String) key, (String) value);
-            }
-        }
-    }
-
-    protected final ExtServletContext getContext()
+    public ExtServletContext getContext()
     {
         return this.context;
     }
@@ -118,4 +92,6 @@ public abstract class AbstractHandler
      * @return the {@link Servlet} or {@link Filter} this handler handles.
      */
     protected abstract Object getSubject();
+
+    public abstract Pattern[] getPatterns();
 }

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java?rev=1656064&r1=1656063&r2=1656064&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/FilterHandler.java Fri Jan 30 17:22:31 2015
@@ -20,6 +20,8 @@ import static javax.servlet.http.HttpSer
 import static javax.servlet.http.HttpServletResponse.SC_OK;
 
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.regex.Pattern;
 
 import javax.servlet.Filter;
@@ -30,32 +32,33 @@ import javax.servlet.http.HttpServletRes
 
 import org.apache.felix.http.base.internal.context.ExtServletContext;
 import org.apache.felix.http.base.internal.runtime.FilterInfo;
+import org.apache.felix.http.base.internal.util.PatternUtil;
 
-public final class FilterHandler extends AbstractHandler implements Comparable<FilterHandler>
+public final class FilterHandler extends AbstractHandler<FilterHandler>
 {
     private final Filter filter;
     private final FilterInfo filterInfo;
+    private final Pattern[] patterns;
 
     public FilterHandler(ExtServletContext context, Filter filter, FilterInfo filterInfo)
     {
-        super(context, filterInfo.initParams, filterInfo.name);
+        super(context, filterInfo.getInitParams(), filterInfo.getName());
         this.filter = filter;
         this.filterInfo = filterInfo;
+        // Compose a single array of all patterns & regexs the filter must represent...
+        String[] patterns = getFilterPatterns(filterInfo);
+
+        this.patterns = new Pattern[patterns.length];
+        for (int i = 0; i < patterns.length; i++)
+        {
+            this.patterns[i] = Pattern.compile(patterns[i]);
+        }
     }
 
     @Override
     public int compareTo(FilterHandler other)
     {
-        if (other.filterInfo.ranking == this.filterInfo.ranking)
-        {
-            if (other.filterInfo.serviceId == this.filterInfo.serviceId)
-            {
-                return 0;
-            }
-            return other.filterInfo.serviceId > this.filterInfo.serviceId ? -1 : 1;
-        }
-
-        return (other.filterInfo.ranking > this.filterInfo.ranking) ? 1 : -1;
+        return this.filterInfo.compareTo(other.filterInfo);
     }
 
     @Override
@@ -69,59 +72,33 @@ public final class FilterHandler extends
         return this.filter;
     }
 
-    public String getPattern()
+    public FilterInfo getFilterInfo()
     {
-        final StringBuilder sb = new StringBuilder();
-        boolean first = true;
-        if ( this.filterInfo.regexs != null )
-        {
-            for(final String p : this.filterInfo.regexs)
-            {
-                if ( first )
-                {
-                    first = false;
-                }
-                else
-                {
-                    sb.append(", ");
-                }
-                sb.append(p);
-            }
-        }
-        if ( this.filterInfo.patterns != null )
-        {
-            for(final String p : this.filterInfo.patterns)
-            {
-                if ( first )
-                {
-                    first = false;
-                }
-                else
-                {
-                    sb.append(", ");
-                }
-                sb.append(p);
-            }
-        }
-        return sb.toString();
+        return this.filterInfo;
     }
 
     public int getRanking()
     {
-        return filterInfo.ranking;
+        return filterInfo.getRanking();
     }
 
-    public void handle(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws ServletException, IOException
+    public boolean handle(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws ServletException, IOException
     {
-        final boolean matches = matches(req.getPathInfo());
-        if (matches)
+        if (getContext().handleSecurity(req, res))
         {
-            doHandle(req, res, chain);
+            this.filter.doFilter(req, res, chain);
+
+            return true;
         }
-        else
+
+        // 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))
         {
-            chain.doFilter(req, res);
+            res.sendError(SC_FORBIDDEN);
         }
+
+        return false;
     }
 
     @Override
@@ -130,60 +107,34 @@ public final class FilterHandler extends
         this.filter.init(new FilterConfigImpl(getName(), getContext(), getInitParams()));
     }
 
-    public boolean matches(String uri)
+    @Override
+    protected Object getSubject()
     {
-        // assume root if uri is null
-        if (uri == null)
-        {
-            uri = "/";
-        }
-
-        if ( this.filterInfo.patterns != null )
-        {
-            for(final String p : this.filterInfo.patterns)
-            {
-                if ( Pattern.compile(p.replace(".", "\\.").replace("*", ".*")).matcher(uri).matches() )
-                {
-                    return true;
-                }
-            }
-        }
-        if ( this.filterInfo.regexs != null )
-        {
-            for(final String p : this.filterInfo.regexs)
-            {
-                if ( Pattern.compile(p).matcher(uri).matches() )
-                {
-                    return true;
-                }
-            }
-        }
-
-        // TODO implement servlet name matching
-
-        return false;
+        return this.filter;
     }
 
-    final void doHandle(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws ServletException, IOException
+    private static String[] getFilterPatterns(FilterInfo filterInfo)
     {
-        if (getContext().handleSecurity(req, res))
+        List<String> result = new ArrayList<String>();
+        if (filterInfo.getPatterns() != null)
         {
-            this.filter.doFilter(req, res, chain);
+            for (int i = 0; i < filterInfo.getPatterns().length; i++)
+            {
+                result.add(PatternUtil.convertToRegEx(filterInfo.getPatterns()[i]));
+            }
         }
-        else
+        if (filterInfo.getRegexs() != null)
         {
-            // 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))
+            for (int i = 0; i < filterInfo.getRegexs().length; i++)
             {
-                res.sendError(SC_FORBIDDEN);
+                result.add(filterInfo.getRegexs()[i]);
             }
         }
+        return result.toArray(new String[result.size()]);
     }
 
     @Override
-    protected Object getSubject()
-    {
-        return this.filter;
+    public Pattern[] getPatterns() {
+        return this.patterns;
     }
 }

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java?rev=1656064&r1=1656063&r2=1656064&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HandlerRegistry.java Fri Jan 30 17:22:31 2015
@@ -16,129 +16,234 @@
  */
 package org.apache.felix.http.base.internal.handler;
 
+import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashSet;
+import java.util.HashMap;
 import java.util.Iterator;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
+import java.util.List;
+import java.util.Map;
 
+import javax.servlet.DispatcherType;
 import javax.servlet.Filter;
 import javax.servlet.Servlet;
 import javax.servlet.ServletException;
 
+import org.apache.felix.http.base.internal.runtime.ContextInfo;
+import org.apache.felix.http.base.internal.runtime.FilterInfo;
 import org.apache.felix.http.base.internal.runtime.ServletInfo;
 import org.osgi.service.http.NamespaceException;
 
 public final class HandlerRegistry
 {
-    private final ConcurrentMap<Filter, FilterHandler> filterMap = new ConcurrentHashMap<Filter, FilterHandler>();
-    private final ConcurrentMap<String, ServletHandler> aliasMap = new ConcurrentHashMap<String, ServletHandler>();
-    private volatile ServletHandler[] servlets;
-    private volatile FilterHandler[] filters;
+    private final Map<Servlet, ServletHandler> servletMap = new HashMap<Servlet, ServletHandler>();
+    private final Map<Filter, FilterHandler> filterMap = new HashMap<Filter, FilterHandler>();
+    private final Map<String, Servlet> servletPatternMap= new HashMap<String, Servlet>();
+    private volatile HandlerMapping<ServletHandler> servletMapping = new HandlerMapping<ServletHandler>();
+    private volatile HandlerMapping<FilterHandler> filterMapping = new HandlerMapping<FilterHandler>();
+    private volatile ErrorsMapping errorsMapping = new ErrorsMapping();
 
-    public HandlerRegistry()
+    public synchronized void addErrorServlet(String errorPage, ServletHandler handler) throws ServletException
     {
-        servlets = new ServletHandler[0];
-        filters = new FilterHandler[0];
+        this.errorsMapping.addErrorServlet(errorPage, handler);
     }
 
-    public ServletHandler[] getServlets()
+    public synchronized void addFilter(FilterHandler handler) throws ServletException
     {
-        return servlets;
+        if (this.filterMap.containsKey(handler.getFilter()))
+        {
+            throw new ServletException("Filter instance already registered");
+        }
+
+        handler.init();
+        this.filterMap.put(handler.getFilter(), handler);
+
+        updateFilterMapping();
+    }
+
+    /**
+     * Add a new servlet.
+     */
+    public synchronized void addServlet(ContextInfo contextInfo, ServletHandler handler) throws ServletException, NamespaceException
+    {
+        if (this.servletMap.containsKey(handler.getServlet()))
+        {
+            // Do not destroy the servlet as the same instance was already registered
+            throw new ServletException("Servlet instance " + handler.getName() + " already registered");
+        }
+
+        // Can be null in case of error-handling servlets...
+        String[] patterns = handler.getServletInfo().getPatterns();
+        int length = patterns == null ? 0 : patterns.length;
+
+        for (int i = 0; i < length; i++)
+        {
+            String pattern = contextInfo != null ? contextInfo.getFullPath(patterns[i]) : patterns[i];
+            if (this.servletPatternMap.containsKey(pattern))
+            {
+                throw new ServletException("Servlet instance " + handler.getName() + " already registered");
+            }
+            this.servletPatternMap.put(pattern, handler.getServlet());
+        }
+
+        handler.init();
+        this.servletMap.put(handler.getServlet(), handler);
+
+        updateServletMapping();
     }
 
-    public FilterHandler[] getFilters()
+    public ErrorsMapping getErrorsMapping()
     {
-        return filters;
+        return this.errorsMapping;
     }
 
-    public void addServlet(final ServletHandler handler)
-    throws ServletException, NamespaceException
+    public FilterHandler[] getFilterHandlers(ServletHandler servletHandler, DispatcherType dispatcherType, String requestURI)
     {
-        handler.init();
+        // See Servlet 3.0 specification, section 6.2.4...
+        List<FilterHandler> result = new ArrayList<FilterHandler>();
+        result.addAll(this.filterMapping.getAllMatches(requestURI));
 
-        if (aliasMap.putIfAbsent(handler.getAlias(), handler) != null)
+        // TODO this is not the most efficient/fastest way of doing this...
+        Iterator<FilterHandler> iter = result.iterator();
+        while (iter.hasNext())
         {
-            handler.destroy();
-            throw new NamespaceException("Servlet with alias '" + handler.getAlias() + "' already registered");
+            if (!referencesDispatcherType(iter.next(), dispatcherType))
+            {
+                iter.remove();
+            }
         }
 
-        updateServletArray();
+        String servletName = (servletHandler != null) ? servletHandler.getName() : null;
+        // TODO this is not the most efficient/fastest way of doing this...
+        for (FilterHandler filterHandler : this.filterMapping.getAllElements())
+        {
+            if (referencesServletByName(filterHandler, servletName))
+            {
+                result.add(filterHandler);
+            }
+        }
+
+        return result.toArray(new FilterHandler[result.size()]);
     }
 
-    public void addFilter(FilterHandler handler) throws ServletException
+    public synchronized Servlet getServletByAlias(String alias)
     {
-        handler.init();
+        return this.servletPatternMap.get(alias);
+    }
+
+    public ServletHandler getServletHandlerByName(String name)
+    {
+        return this.servletMapping.getByName(name);
+    }
+
+    public ServletHandler getServletHander(String requestURI)
+    {
+        return this.servletMapping.getBestMatch(requestURI);
+    }
 
-        // there is a window of opportunity that the servlet/alias was registered between the
-        // previous check and this one, so we have to atomically add if absent here.
-        if (filterMap.putIfAbsent(handler.getFilter(), handler) != null)
+    public synchronized void removeAll()
+    {
+        for (Iterator<ServletHandler> it = servletMap.values().iterator(); it.hasNext(); )
         {
-            // Do not destroy the filter as the same instance was already registered
-            throw new ServletException("Filter instance already registered");
+            ServletHandler handler = it.next();
+            it.remove();
+            handler.destroy();
+        }
+
+        for (Iterator<FilterHandler> it = filterMap.values().iterator(); it.hasNext(); )
+        {
+            FilterHandler handler = it.next();
+            it.remove();
+            handler.destroy();
         }
 
-        updateFilterArray();
+        this.servletMap.clear();
+        this.filterMap.clear();
+        this.servletPatternMap.clear();
+        this.errorsMapping.clear();
+
+        updateServletMapping();
+        updateFilterMapping();
     }
 
-    public Set<Servlet> removeServlet(final ServletInfo servletInfo, final boolean destroy)
+    public synchronized void removeFilter(Filter filter, final boolean destroy)
     {
-        final Set<Servlet> servletInstances = new HashSet<Servlet>();
-        boolean update = false;
-        for (Iterator<ServletHandler> it = aliasMap.values().iterator(); it.hasNext(); )
+        FilterHandler handler = this.filterMap.remove(filter);
+        if (handler != null)
         {
-            final ServletHandler handler = it.next();
-            if (handler.getServletInfo().compareTo(servletInfo) == 0 ) {
-                it.remove();
-                servletInstances.add(handler.getServlet());
+            updateFilterMapping();
+            if (destroy)
+            {
+                handler.destroy();
+            }
+        }
+    }
+
+    public synchronized Filter removeFilter(final FilterInfo filterInfo, final boolean destroy)
+    {
+        for(final FilterHandler handler : this.filterMap.values())
+        {
+            if ( handler.getFilterInfo().compareTo(filterInfo) == 0)
+            {
+                this.filterMap.remove(handler.getFilter());
+                updateFilterMapping();
                 if (destroy)
                 {
                     handler.destroy();
                 }
-                update = true;
+                return handler.getFilter();
             }
         }
-        if ( update )
-        {
-            updateServletArray();
-        }
-
-        return servletInstances;
+        return null;
     }
 
-    /**
-     * Support for old Http Service registrations
-     * @param servlet
-     * @param destroy
-     */
-    public void removeServlet(final Servlet servlet, final boolean destroy)
+    public synchronized Servlet removeServlet(final ContextInfo contextInfo, ServletInfo servletInfo, final boolean destroy)
     {
-        boolean update = false;
-        for (Iterator<ServletHandler> it = aliasMap.values().iterator(); it.hasNext(); )
+        for(final ServletHandler handler : this.servletMap.values())
         {
-            ServletHandler handler = it.next();
-            if (handler.getServlet() == servlet ) {
-                it.remove();
+            if ( handler.getServletInfo().compareTo(servletInfo) == 0 )
+            {
+                this.servletMap.remove(handler.getServlet());
+                updateServletMapping();
+
+                // Can be null in case of error-handling servlets...
+                String[] patterns = handler.getServletInfo().getPatterns();
+                int length = patterns == null ? 0 : patterns.length;
+
+                for (int i = 0; i < length; i++)
+                {
+                    this.servletPatternMap.remove(contextInfo.getFullPath(patterns[i]));
+                }
+
+                this.errorsMapping.removeServlet(handler.getServlet());
+
                 if (destroy)
                 {
                     handler.destroy();
                 }
-                update = true;
+                return handler.getServlet();
             }
         }
-        if ( update )
-        {
-            updateServletArray();
-        }
+        return null;
     }
 
-    public void removeFilter(Filter filter, final boolean destroy)
+    public synchronized void removeServlet(Servlet servlet, final boolean destroy)
     {
-        FilterHandler handler = filterMap.remove(filter);
+        ServletHandler handler = this.servletMap.remove(servlet);
         if (handler != null)
         {
-            updateFilterArray();
+            updateServletMapping();
+
+            // Can be null in case of error-handling servlets...
+            String[] patterns = handler.getServletInfo().getPatterns();
+            int length = patterns == null ? 0 : patterns.length;
+
+            for (int i = 0; i < length; i++)
+            {
+                this.servletPatternMap.remove(patterns[i]);
+            }
+
+            this.errorsMapping.removeServlet(servlet);
+
             if (destroy)
             {
                 handler.destroy();
@@ -146,52 +251,32 @@ public final class HandlerRegistry
         }
     }
 
-    public Servlet getServletByAlias(String alias)
+    private boolean referencesDispatcherType(FilterHandler handler, DispatcherType dispatcherType)
     {
-        final ServletHandler handler = aliasMap.get(alias);
-        if ( handler != null ) {
-            return handler.getServlet();
-        }
-        return null;
+        return Arrays.asList(handler.getFilterInfo().getDispatcher()).contains(dispatcherType);
     }
 
-    public void addErrorServlet(String errorPage, ServletHandler handler) throws ServletException
+    private boolean referencesServletByName(FilterHandler handler, String servletName)
     {
-        // TODO
-    }
-
-    public void removeAll()
-    {
-        for (Iterator<ServletHandler> it = aliasMap.values().iterator(); it.hasNext(); )
+        if (servletName == null)
         {
-            ServletHandler handler = it.next();
-            it.remove();
-
-            handler.destroy();
+            return false;
         }
-
-        for (Iterator<FilterHandler> it = filterMap.values().iterator(); it.hasNext(); )
+        String[] names = handler.getFilterInfo().getServletNames();
+        if (names != null && names.length > 0)
         {
-            FilterHandler handler = it.next();
-            it.remove();
-            handler.destroy();
+            return Arrays.asList(names).contains(servletName);
         }
-
-        updateServletArray();
-        updateFilterArray();
+        return false;
     }
 
-    private void updateServletArray()
+    private void updateFilterMapping()
     {
-        final ServletHandler[] tmp = aliasMap.values().toArray(new ServletHandler[aliasMap.size()]);
-        Arrays.sort(tmp);
-        servlets = tmp;
+        this.filterMapping = new HandlerMapping<FilterHandler>(this.filterMap.values());
     }
 
-    private void updateFilterArray()
+    private void updateServletMapping()
     {
-        final FilterHandler[] tmp = filterMap.values().toArray(new FilterHandler[filterMap.size()]);
-        Arrays.sort(tmp);
-        filters = tmp;
+        this.servletMapping = new HandlerMapping<ServletHandler>(this.servletMap.values());
     }
 }

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpServicePlugin.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpServicePlugin.java?rev=1656064&r1=1656063&r2=1656064&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpServicePlugin.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/HttpServicePlugin.java Fri Jan 30 17:22:31 2015
@@ -53,7 +53,7 @@ public class HttpServicePlugin extends H
 
     public void register()
     {
-        final Dictionary<String, Object> props = new Hashtable<String, Object>();
+        Dictionary<String, Object> props = new Hashtable<String, Object>();
         props.put(Constants.SERVICE_VENDOR, "Apache Software Foundation");
         props.put(Constants.SERVICE_DESCRIPTION, "HTTP Service Web Console Plugin");
         props.put("felix.webconsole.label", "httpservice");
@@ -88,14 +88,14 @@ public class HttpServicePlugin extends H
         pw.println("<th class=\"header\">${Bundle}</th>");
         pw.println("</tr></thead>");
 
-        FilterHandler[] filters = registry.getFilters();
+        FilterHandler[] filters = new FilterHandler[0]; // XXX was: registry.getFilters();
         Arrays.sort(filters);
         String rowClass = "odd";
         for (FilterHandler filter : filters)
         {
             pw.println("<tr class=\"" + rowClass + " ui-state-default\">");
-            pw.println("<td>" + filter.getPattern() + "</td>");
-            pw.println("<td>" + filter.getFilter().getClass().getName() + "(" + filter.getRanking() + ")" + "</td>");
+//            pw.println("<td>" + Arrays.toString(filter.getPatternStrings()) + "</td>"); // XXX
+//            pw.println("<td>" + filter.getFilter().getClass().getName() + "(" + filter.getRanking() + ")" + "</td>");
 
             printBundleDetails(pw, filter.getFilter().getClass());
 
@@ -122,14 +122,14 @@ public class HttpServicePlugin extends H
         pw.println("<th class=\"header\">${Bundle}</th>");
         pw.println("</tr></thead>");
 
-        ServletHandler[] servlets = registry.getServlets();
+        ServletHandler[] servlets = new ServletHandler[0]; // XXX was: registry.getServlets();
         String rowClass = "odd";
         for (ServletHandler servlet : servlets)
         {
 
             pw.println("<tr class=\"" + rowClass + " ui-state-default\">");
-            pw.println("<td>" + servlet.getAlias() + "</td>");
-            pw.println("<td>" + servlet.getServlet().getClass().getName() + "</td>");
+//            pw.println("<td>" + Arrays.toString(servlet.getPatternStrings()) + "</td>"); // XXX
+//            pw.println("<td>" + servlet.getServlet().getClass().getName() + "</td>");
 
             printBundleDetails(pw, servlet.getServlet().getClass());
 
@@ -154,33 +154,30 @@ public class HttpServicePlugin extends H
         pw.println("HTTP Service Details:");
         pw.println();
         pw.println("Registered Servlet Services");
-        ServletHandler[] servlets = registry.getServlets();
+        ServletHandler[] servlets = new ServletHandler[0]; // XXX was: registry.getServlets();
         for (ServletHandler servlet : servlets)
         {
-            pw.println("Alias : " + servlet.getAlias());
-
+//            pw.println("Patterns : " + Arrays.toString(servlet.getPatternStrings())); // XXX
             addSpace(pw, 1);
-            pw.println("Class  :" + servlet.getServlet().getClass().getName());
+            pw.println("Class    : " + servlet.getServlet().getClass().getName());
             addSpace(pw, 1);
-            pw.println("Bundle :" + getBundleDetails(servlet.getServlet().getClass()));
-
+            pw.println("Bundle   : " + getBundleDetails(servlet.getServlet().getClass()));
         }
 
         pw.println();
 
         pw.println("Registered Filter Services");
-        FilterHandler[] filters = registry.getFilters();
+        FilterHandler[] filters = new FilterHandler[0]; // XXX was: registry.getFilters();
         Arrays.sort(filters);
         for (FilterHandler filter : filters)
         {
-            pw.println("Pattern : " + filter.getPattern());
-
+//            pw.println("Patterns : " + Arrays.toString(filter.getPatternStrings())); // XXX
             addSpace(pw, 1);
-            pw.println("Ranking :" + filter.getRanking());
+//            pw.println("Ranking  : " + filter.getRanking()); // XXX
             addSpace(pw, 1);
-            pw.println("Class   :" + filter.getFilter().getClass().getName());
+            pw.println("Class    : " + filter.getFilter().getClass().getName());
             addSpace(pw, 1);
-            pw.println("Bundle  :" + getBundleDetails(filter.getFilter().getClass()));
+            pw.println("Bundle   : " + getBundleDetails(filter.getFilter().getClass()));
         }
     }
 

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java?rev=1656064&r1=1656063&r2=1656064&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/handler/ServletHandler.java Fri Jan 30 17:22:31 2015
@@ -16,264 +16,85 @@
  */
 package org.apache.felix.http.base.internal.handler;
 
-import static javax.servlet.RequestDispatcher.FORWARD_CONTEXT_PATH;
-import static javax.servlet.RequestDispatcher.FORWARD_PATH_INFO;
-import static javax.servlet.RequestDispatcher.FORWARD_QUERY_STRING;
-import static javax.servlet.RequestDispatcher.FORWARD_REQUEST_URI;
-import static javax.servlet.RequestDispatcher.FORWARD_SERVLET_PATH;
-import static javax.servlet.RequestDispatcher.INCLUDE_CONTEXT_PATH;
-import static javax.servlet.RequestDispatcher.INCLUDE_PATH_INFO;
-import static javax.servlet.RequestDispatcher.INCLUDE_QUERY_STRING;
-import static javax.servlet.RequestDispatcher.INCLUDE_REQUEST_URI;
-import static javax.servlet.RequestDispatcher.INCLUDE_SERVLET_PATH;
 import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
 import static javax.servlet.http.HttpServletResponse.SC_OK;
-import static org.apache.felix.http.base.internal.util.UriUtils.concat;
 
 import java.io.IOException;
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import javax.servlet.DispatcherType;
-import javax.servlet.RequestDispatcher;
 import javax.servlet.Servlet;
 import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.felix.http.base.internal.context.ExtServletContext;
+import org.apache.felix.http.base.internal.runtime.ContextInfo;
 import org.apache.felix.http.base.internal.runtime.ServletInfo;
+import org.apache.felix.http.base.internal.util.PatternUtil;
 
 /**
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-public final class ServletHandler extends AbstractHandler implements Comparable<ServletHandler>
+public final class ServletHandler extends AbstractHandler<ServletHandler>
 {
-    private class RequestDispatcherImpl implements RequestDispatcher
-    {
-        final String servletPath = "/".equals(getAlias()) ? "" : getAlias(); // XXX handle wildcard aliases!
-        final String requestURI;
-        final String pathInfo;
-        final String query;
-        final boolean named;
-
-        public RequestDispatcherImpl()
-        {
-            this.requestURI = null;
-            this.pathInfo = null;
-            this.query = null;
-            this.named = true;
-        }
+    private final ServletInfo servletInfo;
 
-        public RequestDispatcherImpl(String uri, String pathInContext, String query)
-        {
-            this.requestURI = uri;
-            this.pathInfo = this.servletPath.equals(pathInContext) ? null : pathInContext;
-            this.query = query;
-            this.named = false;
-        }
+    private final Servlet servlet;
 
-        @Override
-        public void forward(ServletRequest req, ServletResponse res) throws ServletException, IOException
-        {
-            if (res.isCommitted())
-            {
-                throw new ServletException("Response has been committed");
-            }
-            else
-            {
-                // See section 9.4 of Servlet 3.0 spec
-                res.resetBuffer();
-            }
-
-            // Since we're already created this RequestDispatcher for *this* servlet handler, we do not need to
-            // recheck whether its patch matches, but instead can directly handle the forward-request...
-            doHandle(new ServletRequestWrapper((HttpServletRequest) req, this, DispatcherType.FORWARD), (HttpServletResponse) res);
-
-            // After a forward has taken place, the results should be committed,
-            // see section 9.4 of Servlet 3.0 spec...
-            if (!req.isAsyncStarted())
-            {
-                res.flushBuffer();
-                res.getWriter().close();
-            }
-        }
+    private final Pattern[] patterns;
 
-        @Override
-        public void include(ServletRequest req, ServletResponse res) throws ServletException, IOException
-        {
-            // Since we're already created this RequestDispatcher for *this* servlet handler, we do not need to
-            // recheck whether its patch matches, but instead can directly handle the include-request...
-            doHandle(new ServletRequestWrapper((HttpServletRequest) req, this, DispatcherType.INCLUDE), (HttpServletResponse) res);
-        }
+    private final long contextServiceId;
 
-        boolean isNamedDispatcher()
-        {
-            return this.named;
-        }
-    }
-
-    private static class ServletRequestWrapper extends HttpServletRequestWrapper
+    public ServletHandler(final ContextInfo contextInfo,
+                          final ExtServletContext context,
+                          final ServletInfo servletInfo,
+                          final Servlet servlet)
     {
-        private final RequestDispatcherImpl dispatcher;
-        private final DispatcherType type;
-
-        public ServletRequestWrapper(HttpServletRequest req, RequestDispatcherImpl dispatcher, DispatcherType type)
-        {
-            super(req);
-            this.dispatcher = dispatcher;
-            this.type = type;
-        }
-
-        @Override
-        public Object getAttribute(String name)
-        {
-            HttpServletRequest request = (HttpServletRequest) getRequest();
-            if (isInclusionDispatcher())
-            {
-                if (INCLUDE_REQUEST_URI.equals(name))
-                {
-                    return concat(request.getContextPath(), this.dispatcher.requestURI);
-                }
-                else if (INCLUDE_CONTEXT_PATH.equals(name))
-                {
-                    return request.getContextPath();
-                }
-                else if (INCLUDE_SERVLET_PATH.equals(name))
-                {
-                    return this.dispatcher.servletPath;
-                }
-                else if (INCLUDE_PATH_INFO.equals(name))
-                {
-                    return this.dispatcher.pathInfo;
-                }
-                else if (INCLUDE_QUERY_STRING.equals(name))
-                {
-                    return this.dispatcher.query;
-                }
-            }
-            else if (isForwardingDispatcher())
-            {
-                // NOTE: the forward.* attributes *always* yield the *original* values...
-                if (FORWARD_REQUEST_URI.equals(name))
-                {
-                    return super.getRequestURI();
-                }
-                else if (FORWARD_CONTEXT_PATH.equals(name))
-                {
-                    return request.getContextPath();
-                }
-                else if (FORWARD_SERVLET_PATH.equals(name))
-                {
-                    return super.getServletPath();
-                }
-                else if (FORWARD_PATH_INFO.equals(name))
-                {
-                    return super.getPathInfo();
-                }
-                else if (FORWARD_QUERY_STRING.equals(name))
-                {
-                    return super.getQueryString();
-                }
-            }
-
-            return super.getAttribute(name);
-        }
-
-        @Override
-        public DispatcherType getDispatcherType()
-        {
-            return this.type;
-        }
-
-        @Override
-        public String getPathInfo()
-        {
-            if (isForwardingDispatcher())
-            {
-                return this.dispatcher.pathInfo;
-            }
-            return super.getPathInfo();
-        }
-
-        @Override
-        public String getRequestURI()
-        {
-            if (isForwardingDispatcher())
-            {
-                return concat(getContextPath(), this.dispatcher.requestURI);
-            }
-            return super.getRequestURI();
-        }
+        super(context, servletInfo.getInitParams(), servletInfo.getName());
+        this.servlet = servlet;
+        this.servletInfo = servletInfo;
 
-        @Override
-        public String getServletPath()
-        {
-            if (isForwardingDispatcher())
-            {
-                return this.dispatcher.servletPath;
-            }
-            return super.getServletPath();
-        }
+        // Can be null in case of error-handling servlets...
+        String[] patterns = this.servletInfo.getPatterns();
+        final int length = patterns == null ? 0 : patterns.length;
 
-        @Override
-        public String toString()
+        this.patterns = new Pattern[length];
+        for (int i = 0; i < length; i++)
         {
-            return getClass().getSimpleName() + "->" + super.getRequest();
+            String pattern = (contextInfo == null ? patterns[i] : contextInfo.getFullPath(patterns[i]));
+            this.patterns[i] = Pattern.compile(PatternUtil.convertToRegEx(pattern));
         }
-
-        private boolean isForwardingDispatcher()
+        if ( contextInfo != null )
         {
-            return DispatcherType.FORWARD == this.type && !this.dispatcher.isNamedDispatcher();
+            this.contextServiceId = contextInfo.getServiceId();
         }
-
-        private boolean isInclusionDispatcher()
+        else
         {
-            return DispatcherType.INCLUDE == this.type && !this.dispatcher.isNamedDispatcher();
+            this.contextServiceId = -1;
         }
     }
 
-    private final ServletInfo servletInfo;
-
-    private final Servlet servlet;
-
-    private final Pattern pattern;
-
-    private final String alias;
-
-    public ServletHandler(final ExtServletContext context,
-                          final ServletInfo servletInfo,
-                          final Servlet servlet,
-                          final String alias)
+    @Override
+    public int compareTo(ServletHandler other)
     {
-        super(context, servletInfo.getInitParams(), servletInfo.getName());
-        this.servlet = servlet;
-        this.pattern = Pattern.compile(alias.replace(".", "\\.").replace("*", ".*"));
-        this.alias = alias;
-        this.servletInfo = servletInfo;
+        return getId() - other.getId();
     }
 
-    @Override
-    public int compareTo(ServletHandler other)
+    public String determineServletPath(String uri)
     {
-        int result = other.alias.length() - this.alias.length();
-        if ( result == 0 )
+        if (uri == null)
         {
-            result = this.alias.compareTo(other.alias);
+            uri = "/";
         }
-        return result;
-    }
 
-    public RequestDispatcher createNamedRequestDispatcher()
-    {
-        return new RequestDispatcherImpl();
-    }
+        Matcher matcher = this.patterns[0].matcher(uri);
+        if (matcher.find(0))
+        {
+            return matcher.groupCount() > 0 ? matcher.group(1) : matcher.group();
+        }
 
-    public RequestDispatcher createRequestDispatcher(String path, String pathInContext, String query)
-    {
-        return new RequestDispatcherImpl(path, pathInContext, query);
+        return null;
     }
 
     @Override
@@ -282,43 +103,15 @@ public final class ServletHandler extend
         this.servlet.destroy();
     }
 
-    public String getAlias()
-    {
-        return this.alias;
-    }
-
     public Servlet getServlet()
     {
         return this.servlet;
     }
 
-    public boolean handle(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
+    @Override
+    public Pattern[] getPatterns()
     {
-        String path;
-        if (DispatcherType.INCLUDE == req.getDispatcherType())
-        {
-            path = (String) req.getAttribute(INCLUDE_SERVLET_PATH);
-        }
-        else if (DispatcherType.FORWARD == req.getDispatcherType())
-        {
-            path = (String) req.getAttribute(FORWARD_SERVLET_PATH);
-        }
-        else if (DispatcherType.ASYNC == req.getDispatcherType())
-        {
-            path = (String) req.getAttribute("javax.servlet.async.path_info");
-        }
-        else
-        {
-            path = req.getPathInfo();
-        }
-
-        final boolean matches = matches(path);
-        if (matches)
-        {
-            doHandle(req, res);
-        }
-
-        return matches;
+        return this.patterns;
     }
 
     @Override
@@ -327,22 +120,23 @@ public final class ServletHandler extend
         this.servlet.init(new ServletConfigImpl(getName(), getContext(), getInitParams()));
     }
 
-    public boolean matches(String uri)
+    public boolean handle(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
     {
-        // TODO handle wildcard aliases and extension specs...
-        if (uri == null)
-        {
-            return this.alias.equals("/");
-        }
-        else if (this.alias.equals("/"))
+        if (getContext().handleSecurity(req, res))
         {
-            return uri.startsWith(this.alias);
+            this.servlet.service(req, res);
+
+            return true;
         }
-        else if ( uri.equals(this.alias) || uri.startsWith(this.alias + "/") )
+
+        // 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))
         {
-            return true;
+            res.sendError(SC_FORBIDDEN);
         }
-        return this.pattern.matcher(uri).matches();
+
+        return false;
     }
 
     public ServletInfo getServletInfo()
@@ -350,33 +144,14 @@ public final class ServletHandler extend
         return this.servletInfo;
     }
 
-    final void doHandle(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
-    {
-        // Only wrap the original ServletRequest in case we're handling plain requests,
-        // not inclusions or forwards from servlets. Should solve FELIX-2774 and FELIX-3054...
-        if (DispatcherType.REQUEST == req.getDispatcherType())
-        {
-            req = new ServletHandlerRequest(req, getContext(), this.alias);
-        }
-
-        if (getContext().handleSecurity(req, res))
-        {
-            this.servlet.service(req, res);
-        }
-        else
-        {
-            // 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.sendError(SC_FORBIDDEN);
-            }
-        }
-    }
-
     @Override
     protected Object getSubject()
     {
         return this.servlet;
     }
+
+    public long getContextServiceId()
+    {
+        return this.contextServiceId;
+    }
 }

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/AbstractInfo.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/AbstractInfo.java?rev=1656064&r1=1656063&r2=1656064&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/AbstractInfo.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/AbstractInfo.java Fri Jan 30 17:22:31 2015
@@ -119,6 +119,19 @@ public abstract class AbstractInfo<T> im
             {
                 return 0;
             }
+            // service id might be negative, we have to change the behaviour in that case
+            if ( this.serviceId < 0 )
+            {
+                if ( other.serviceId > 0 )
+                {
+                    return -1;
+                }
+                return other.serviceId < this.serviceId ? -1 : 1;
+            }
+            if ( other.serviceId < 0 )
+            {
+                return -1;
+            }
             return other.serviceId > this.serviceId ? -1 : 1;
         }
 

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ContextInfo.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ContextInfo.java?rev=1656064&r1=1656063&r2=1656064&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ContextInfo.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/ContextInfo.java Fri Jan 30 17:22:31 2015
@@ -31,10 +31,21 @@ public final class ContextInfo extends A
 
     private final String path;
 
+    private final String prefix;
+
     public ContextInfo(final ServiceReference<ServletContextHelper> ref) {
         super(ref);
         this.name = this.getStringProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME);
         this.path = this.getStringProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH);
+        String prefix = null;
+        if ( !isEmpty(this.path) )
+        {
+            if ( !this.path.equals("/") && this.path.length() > 1 )
+            {
+                prefix = this.path.substring(0, this.path.length() - 1);
+            }
+        }
+        this.prefix = prefix;
     }
 
     @Override
@@ -53,4 +64,18 @@ public final class ContextInfo extends A
     {
         return this.path;
     }
+
+    public String getPrefix()
+    {
+        return this.prefix;
+    }
+
+    public String getFullPath(final String path)
+    {
+        if ( this.prefix == null )
+        {
+            return path;
+        }
+        return this.prefix.concat(path);
+    }
 }

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/FilterInfo.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/FilterInfo.java?rev=1656064&r1=1656063&r2=1656064&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/FilterInfo.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/runtime/FilterInfo.java Fri Jan 30 17:22:31 2015
@@ -24,10 +24,10 @@ import javax.servlet.DispatcherType;
 import javax.servlet.Filter;
 
 import org.osgi.dto.DTO;
+import org.osgi.framework.ServiceReference;
 import org.osgi.service.http.HttpContext;
 import org.osgi.service.http.runtime.dto.FilterDTO;
-
-import aQute.bnd.annotation.ConsumerType;
+import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
 
 /**
  * Provides registration information for a {@link Filter}, and is used to programmatically register {@link Filter}s.
@@ -37,13 +37,18 @@ import aQute.bnd.annotation.ConsumerType
  *
  * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
  */
-@ConsumerType
-public final class FilterInfo
+public final class FilterInfo extends AbstractInfo<Filter>
 {
     /**
-     * The name of the servlet.
+     * Properties starting with this prefix are passed as filter init parameters to the
+     * {@code init()} method of the filter.
+     */
+    private static final String FILTER_INIT_PREFIX = "filter.init.";
+
+    /**
+     * The name of the filter.
      */
-    public String name;
+    private final String name;
 
     /**
      * The request mappings for the servlet.
@@ -52,7 +57,7 @@ public final class FilterInfo
      * Note that these patterns should conform to the Servlet specification.
      * </p>
      */
-    public String[] patterns;
+    private final String[] patterns;
 
     /**
      * The servlet names for the servlet filter.
@@ -60,7 +65,7 @@ public final class FilterInfo
      * The specified names are used to determine the servlets whose requests are mapped to the servlet filter.
      * </p>
      */
-    public String[] servletNames;
+    private final String[] servletNames;
 
     /**
      * The request mappings for the servlet filter.
@@ -69,18 +74,12 @@ public final class FilterInfo
      * 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;
+    private final 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;
-    public long serviceId;
+    private final boolean asyncSupported;
 
     /**
      * The dispatcher associations for the servlet filter.
@@ -89,16 +88,108 @@ public final class FilterInfo
      * See {@link DispatcherType} and Servlet 3.0 specification, section 6.2.5.
      * </p>
      */
-    public DispatcherType[] dispatcher = { DispatcherType.REQUEST };
+    private final DispatcherType[] dispatcher;
 
     /**
      * The filter initialization parameters as provided during registration of the filter.
      */
-    public Map<String, String> initParams;
+    private final Map<String, String> initParams;
 
     /**
-     * The {@link HttpContext} for the servlet.
+     * The {@link HttpContext} for the filter.
      */
-    public HttpContext context;
+    private final HttpContext context;
+
+    private final Filter filter;
 
+    public FilterInfo(final ServiceReference<Filter> ref)
+    {
+        super(ref);
+        this.name = getStringProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_NAME);
+        this.asyncSupported = getBooleanProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_ASYNC_SUPPORTED);
+        this.servletNames = getStringArrayProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_SERVLET);
+        this.patterns = getStringArrayProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN);
+        this.regexs = getStringArrayProperty(ref, HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_REGEX);
+        this.initParams = getInitParams(ref, FILTER_INIT_PREFIX);
+        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());
+            }
+            this.dispatcher = dispatchers;
+        }
+        else
+        {
+            this.dispatcher = new DispatcherType[] {DispatcherType.REQUEST};
+        }
+        this.context = null;
+        this.filter = null;
+    }
+
+    /**
+     * Constructor for Http Service
+     */
+    public FilterInfo(final String name,
+            final String regex,
+            final int serviceRanking,
+            final Map<String, String> initParams,
+            final Filter filter,
+            final HttpContext context)
+    {
+        super(serviceRanking);
+        this.name = name;
+        this.patterns = null;
+        this.servletNames = null;
+        this.regexs = new String[] {regex};
+        this.initParams = initParams;
+        this.asyncSupported = false;
+        this.dispatcher = new DispatcherType[] {DispatcherType.REQUEST};
+        this.filter = filter;
+        this.context = context;
+    }
+
+    @Override
+    public boolean isValid()
+    {
+        return super.isValid() && (!isEmpty(this.patterns) || !isEmpty(this.regexs) || !isEmpty(this.servletNames));
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String[] getPatterns() {
+        return patterns;
+    }
+
+    public String[] getServletNames() {
+        return servletNames;
+    }
+
+    public String[] getRegexs() {
+        return regexs;
+    }
+
+    public boolean isAsyncSupported() {
+        return asyncSupported;
+    }
+
+    public DispatcherType[] getDispatcher() {
+        return dispatcher;
+    }
+
+    public Map<String, String> getInitParams() {
+        return initParams;
+    }
+
+    public HttpContext getContext() {
+        return context;
+    }
+
+    public Filter getFilter() {
+        return filter;
+    }
 }



Mime
View raw message