Author: bdekruijff at gmail.com
Date: Tue Jan 25 14:25:33 2011
New Revision: 706

Log:
AMDATU-245 initial version (lots of todos)

Added:
   sandbox/bdekruijff/dispatcher/
   sandbox/bdekruijff/dispatcher/pom.xml
   sandbox/bdekruijff/dispatcher/src/
   sandbox/bdekruijff/dispatcher/src/main/
   sandbox/bdekruijff/dispatcher/src/main/java/
   sandbox/bdekruijff/dispatcher/src/main/java/org/
   sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/
   sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/
   sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/DispatchExtenderFilter.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/DispatchFilterMatcher.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/DispatchServletMatcher.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/DispatcherService.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/context/
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/context/DefaultHttpContext.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/context/ExtServletContext.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/context/HandlerServletContext.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/context/HttpContextManager.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/dispatch/
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/dispatch/FilterPipeline.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/dispatch/HttpFilterChain.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/dispatch/InvocationFilterChain.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/dispatch/NotFoundFilterChain.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/dispatch/ServletPipeline.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/extender/
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/extender/TenantParameterDispatchExtender.java
   sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/filter/
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/filter/DispatchInterceptFilter.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/AbstractHandler.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/AbstractHandlerRegistry.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/FilterConfigImpl.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/FilterHandler.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/FilterHandlerRegistry.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/ServletConfigImpl.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/ServletHandler.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/ServletHandlerRegistry.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/ServletHandlerRequest.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/matcher/
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/matcher/TenantAwareServletMatcher.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/matcher/TenantUnawareServletMatcher.java
   sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/osgi/
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/osgi/DispatcherServiceActivator.java
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/service/
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/service/DispatcherServiceImpl.java
   sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/test/
   
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/test/HelloWorldServlet.java

Added: sandbox/bdekruijff/dispatcher/pom.xml
==============================================================================
--- (empty file)
+++ sandbox/bdekruijff/dispatcher/pom.xml       Tue Jan 25 14:25:33 2011
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.amdatu</groupId>
+    <artifactId>org.amdatu.web</artifactId>
+    <version>0.1.0-SNAPSHOT</version>
+  </parent>
+  <groupId>org.amdatu.web</groupId>
+  <artifactId>dispatcher</artifactId>
+  <packaging>bundle</packaging>
+  <name>Amdatu Web - Dispatcher</name>
+  <description>Provides a Dispatcher implementation</description>
+  <dependencies>
+    <dependency>
+      <groupId>org.amdatu.core</groupId>
+      <artifactId>tenant</artifactId>
+      <scope>provided</scope>
+      <type>bundle</type>
+      <version>0.1.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.http.api</artifactId>
+      <version>2.0.4</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.http.base</artifactId>
+      <version>2.0.4</version>
+      <scope>compile</scope>
+    </dependency>
+    <!--
+      <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.http.whiteboard</artifactId>
+      <version>2.0.4</version>
+      <scope>compile</scope>
+      </dependency>
+    -->
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <configuration>
+          <instructions>
+            <Private-Package> org.amdatu.web.dispatcher.*</Private-Package>
+            
<Bundle-Activator>org.amdatu.web.dispatcher.osgi.DispatcherServiceActivator</Bundle-Activator>
+            
<Bundle-SymbolicName>org.amdatu.web.dispatcher</Bundle-SymbolicName>
+            <Export-Package>
+              org.amdatu.web.dispatcher
+            </Export-Package>
+            
<Embed-Dependency>*;scope=compile;inline=org/apache/felix/http/base/internal/util/**</Embed-Dependency>
+            <Embed-Transitive>true</Embed-Transitive>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/DispatchExtenderFilter.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/DispatchExtenderFilter.java
   Tue Jan 25 14:25:33 2011
@@ -0,0 +1,7 @@
+package org.amdatu.web.dispatcher;
+
+import javax.servlet.Filter;
+
+public interface DispatchExtenderFilter extends Filter {
+
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/DispatchFilterMatcher.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/DispatchFilterMatcher.java
    Tue Jan 25 14:25:33 2011
@@ -0,0 +1,9 @@
+package org.amdatu.web.dispatcher;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.amdatu.web.dispatcher.handler.FilterHandler;
+
+public interface DispatchFilterMatcher {
+    boolean matches(FilterHandler filterHandler, HttpServletRequest 
httpServletRequest);
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/DispatchServletMatcher.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/DispatchServletMatcher.java
   Tue Jan 25 14:25:33 2011
@@ -0,0 +1,9 @@
+package org.amdatu.web.dispatcher;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.amdatu.web.dispatcher.handler.ServletHandler;
+
+public interface DispatchServletMatcher {
+    boolean matches(ServletHandler servletHandler, HttpServletRequest 
httpServletRequest);
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/DispatcherService.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/DispatcherService.java
        Tue Jan 25 14:25:33 2011
@@ -0,0 +1,41 @@
+/*
+    Copyright (C) 2010 Amdatu.org
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.web.dispatcher;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+
+import org.amdatu.web.dispatcher.context.HttpContextManager;
+import org.amdatu.web.dispatcher.dispatch.FilterPipeline;
+import org.osgi.service.log.LogService;
+
+public interface DispatcherService {
+
+    
+    public final static String CONTEXT_ID_KEY = "contextId";
+    public final static String PATTERN_KEY = "pattern";
+    public final static String ALIAS_KEY = "alias";
+    public final static String INIT_KEY_PREFIX = "init.";
+
+//    HttpServlet getServletByAlias(String alias);
+
+    public FilterPipeline getFilterPipeline(HttpServletRequest 
httpServletRequest);
+
+    HttpContextManager getHttpContextManager();
+    LogService getLogService();
+    ServletContext getServletContext();
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/context/DefaultHttpContext.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/context/DefaultHttpContext.java
       Tue Jan 25 14:25:33 2011
@@ -0,0 +1,31 @@
+package org.amdatu.web.dispatcher.context;
+
+import org.osgi.service.http.HttpContext;
+import org.osgi.framework.Bundle;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.net.URL;
+
+public final class DefaultHttpContext implements HttpContext {
+
+    private Bundle m_bundle;
+
+    public DefaultHttpContext(Bundle bundle) {
+        m_bundle = bundle;
+    }
+
+    public String getMimeType(String name) {
+        return null;
+    }
+
+    public URL getResource(String name) {
+        if (name.startsWith("/")) {
+            name = name.substring(1);
+        }
+        return m_bundle.getResource(name);
+    }
+
+    public boolean handleSecurity(HttpServletRequest req, HttpServletResponse 
res) {
+        return true;
+    }
+}
\ No newline at end of file

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/context/ExtServletContext.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/context/ExtServletContext.java
        Tue Jan 25 14:25:33 2011
@@ -0,0 +1,12 @@
+package org.amdatu.web.dispatcher.context;
+
+import java.io.IOException;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public interface ExtServletContext extends ServletContext {
+    public boolean handleSecurity(HttpServletRequest req, HttpServletResponse 
res)
+        throws IOException;
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/context/HandlerServletContext.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/context/HandlerServletContext.java
    Tue Jan 25 14:25:33 2011
@@ -0,0 +1,147 @@
+package org.amdatu.web.dispatcher.context;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Set;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.Servlet;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.felix.http.base.internal.util.MimeTypes;
+import org.osgi.service.http.HttpContext;
+
+public class HandlerServletContext implements ExtServletContext {
+
+    private final ServletContext m_extServletContext;
+    private final HttpContext m_httpContext;
+
+    public HandlerServletContext(ServletContext m_extServletContext2, 
HttpContext httpContext) {
+        m_extServletContext = m_extServletContext2;
+        m_httpContext = httpContext;
+    }
+
+    public Object getAttribute(String key) {
+        return m_extServletContext.getAttribute(key);
+    }
+
+    public Enumeration getAttributeNames() {
+        return m_extServletContext.getAttributeNames();
+    }
+
+    public ServletContext getContext(String uri) {
+        return m_extServletContext.getContext(uri);
+    }
+
+    public String getContextPath() {
+        return m_extServletContext.getContextPath();
+    }
+
+    public String getInitParameter(String key) {
+        return m_extServletContext.getInitParameter(key);
+    }
+
+    public Enumeration getInitParameterNames() {
+        return m_extServletContext.getInitParameterNames();
+    }
+
+    public int getMajorVersion() {
+        return m_extServletContext.getMajorVersion();
+    }
+
+    public String getMimeType(String file) {
+        String type = m_httpContext.getMimeType(file);
+        if (type != null) {
+            return type;
+        }
+        return MimeTypes.get().getByFile(file);
+    }
+
+    public int getMinorVersion() {
+        return m_extServletContext.getMinorVersion();
+    }
+
+    public RequestDispatcher getNamedDispatcher(String path) {
+        return m_extServletContext.getNamedDispatcher(path);
+    }
+
+    public String getRealPath(String path) {
+        return m_extServletContext.getRealPath(path);
+    }
+
+    public RequestDispatcher getRequestDispatcher(String uri) {
+        return m_extServletContext.getRequestDispatcher(uri);
+    }
+
+    public URL getResource(String path) {
+        return m_httpContext.getResource(path);
+
+    }
+
+    public InputStream getResourceAsStream(String path) {
+        URL res = getResource(path);
+        if (res != null) {
+            try {
+                return res.openStream();
+            }
+            catch (IOException e) {}
+        }
+        return null;
+    }
+
+    public Set getResourcePaths(String path) {
+        return m_extServletContext.getResourcePaths(path);
+    }
+
+    public String getServerInfo() {
+        return m_extServletContext.getServerInfo();
+    }
+
+    @SuppressWarnings("deprecation")
+    public Servlet getServlet(String name) throws ServletException {
+        return m_extServletContext.getServlet(name);
+    }
+
+    public String getServletContextName() {
+        return m_extServletContext.getServletContextName();
+    }
+
+    @SuppressWarnings("deprecation")
+    public Enumeration getServletNames() {
+        return m_extServletContext.getServletNames();
+    }
+
+    @SuppressWarnings("deprecation")
+    public Enumeration getServlets() {
+        return m_extServletContext.getServlets();
+    }
+
+    public void log(String message) {
+        m_extServletContext.log(message);
+    }
+
+    public void log(Exception exception, String message) {
+        m_extServletContext.log(exception, message);
+    }
+
+    public void log(String message, Throwable cause) {
+        m_extServletContext.log(message, cause);
+    }
+
+    public void removeAttribute(String key) {
+        m_extServletContext.removeAttribute(key);
+    }
+
+    public void setAttribute(String key, Object value) {
+        m_extServletContext.setAttribute(key, value);
+    }
+
+    public boolean handleSecurity(HttpServletRequest arg0, HttpServletResponse 
arg1) throws IOException {
+        return m_httpContext.handleSecurity(arg0, arg1);
+    }
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/context/HttpContextManager.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/context/HttpContextManager.java
       Tue Jan 25 14:25:33 2011
@@ -0,0 +1,44 @@
+package org.amdatu.web.dispatcher.context;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.osgi.framework.Bundle;
+import org.osgi.service.http.HttpContext;
+
+public final class HttpContextManager {
+
+    private final Map<String, HttpContext> m_idHttpContexts = new 
HashMap<String, HttpContext>();
+    private final Map<HttpContext, String> m_httpContextIds = new 
HashMap<HttpContext, String>();
+
+    public HttpContextManager() {
+    }
+
+    public synchronized HttpContext getHttpContext(Bundle bundle, String 
contextId) {
+        String id = createId(bundle, contextId);
+        HttpContext context = m_idHttpContexts.get(id);
+        if (context == null) {
+            context = new DefaultHttpContext(bundle);
+            m_idHttpContexts.put(id, context);
+            m_httpContextIds.put(context, id);
+        }
+        return context;
+    }
+
+    public synchronized void removeHttpContext(HttpContext context) {
+        String id = m_httpContextIds.remove(context);
+        if (id != null) {
+            m_idHttpContexts.remove(id);
+        }
+    }
+
+    public synchronized void addHttpContext(Bundle bundle, String contextId, 
HttpContext context) {
+        String id = createId(bundle, contextId);
+        m_idHttpContexts.put(id, context);
+        m_httpContextIds.put(context, id);
+    }
+
+    private String createId(Bundle bundle, String contextId) {
+        return bundle.getBundleId() + "-" + contextId;
+    }
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/dispatch/FilterPipeline.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/dispatch/FilterPipeline.java
  Tue Jan 25 14:25:33 2011
@@ -0,0 +1,44 @@
+package org.amdatu.web.dispatcher.dispatch;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpServletResponse;
+
+import org.amdatu.web.dispatcher.handler.FilterHandler;
+
+public final class FilterPipeline {
+
+    private final FilterHandler[] m_filterHandlers;
+    private final ServletPipeline m_servletPipeline;
+
+    public FilterPipeline(FilterHandler[] handlers, ServletPipeline 
servletPipeline) {
+        m_filterHandlers = handlers;
+        m_servletPipeline = servletPipeline;
+    }
+
+    public void dispatch(HttpServletRequest req, HttpServletResponse res, 
FilterChain proceedingChain)
+        throws ServletException, IOException {
+        FilterChain chain = new InvocationFilterChain(m_filterHandlers, 
m_servletPipeline, proceedingChain);
+        if (m_servletPipeline.hasServletsMapped()) {
+            req = new RequestWrapper(req);
+        }
+        chain.doFilter(req, res);
+    }
+
+    private final class RequestWrapper extends HttpServletRequestWrapper {
+        public RequestWrapper(HttpServletRequest req) {
+            super(req);
+        }
+
+        @Override
+        public RequestDispatcher getRequestDispatcher(String path) {
+            final RequestDispatcher dispatcher = 
m_servletPipeline.getRequestDispatcher(path);
+            return (null != dispatcher) ? dispatcher : 
super.getRequestDispatcher(path);
+        }
+    }
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/dispatch/HttpFilterChain.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/dispatch/HttpFilterChain.java
 Tue Jan 25 14:25:33 2011
@@ -0,0 +1,20 @@
+package org.amdatu.web.dispatcher.dispatch;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public abstract class HttpFilterChain implements FilterChain {
+    public final void doFilter(ServletRequest req, ServletResponse res)
+        throws IOException, ServletException {
+        doFilter((HttpServletRequest) req, (HttpServletResponse) res);
+    }
+
+    protected abstract void doFilter(HttpServletRequest req, 
HttpServletResponse res)
+        throws IOException, ServletException;
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/dispatch/InvocationFilterChain.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/dispatch/InvocationFilterChain.java
   Tue Jan 25 14:25:33 2011
@@ -0,0 +1,39 @@
+package org.amdatu.web.dispatcher.dispatch;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.amdatu.web.dispatcher.handler.FilterHandler;
+
+public final class InvocationFilterChain
+    extends HttpFilterChain {
+    private final FilterHandler[] handlers;
+    private final ServletPipeline servletPipeline;
+    private final FilterChain proceedingChain;
+    private int index = -1;
+
+    public InvocationFilterChain(FilterHandler[] handlers, ServletPipeline 
servletPipeline, FilterChain proceedingChain) {
+        this.handlers = handlers;
+        this.servletPipeline = servletPipeline;
+        this.proceedingChain = proceedingChain;
+    }
+
+    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.servletPipeline.handle(req, res)) {
+                System.err.println("Request not handled. Returning to parent 
chain... ");
+                this.proceedingChain.doFilter(req, res);
+            }
+        }
+    }
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/dispatch/NotFoundFilterChain.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/dispatch/NotFoundFilterChain.java
     Tue Jan 25 14:25:33 2011
@@ -0,0 +1,15 @@
+package org.amdatu.web.dispatcher.dispatch;
+
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public final class NotFoundFilterChain extends HttpFilterChain {
+
+    protected void doFilter(HttpServletRequest req, HttpServletResponse res)
+        throws IOException, ServletException {
+        res.sendError(HttpServletResponse.SC_NOT_FOUND);
+    }
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/dispatch/ServletPipeline.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/dispatch/ServletPipeline.java
 Tue Jan 25 14:25:33 2011
@@ -0,0 +1,80 @@
+package org.amdatu.web.dispatcher.dispatch;
+
+import java.io.IOException;
+
+import javax.servlet.RequestDispatcher;
+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.amdatu.web.dispatcher.handler.ServletHandler;
+
+public final class ServletPipeline {
+
+    private final ServletHandler[] m_servletHandlers;
+
+    public ServletPipeline(ServletHandler[] handlers) {
+        m_servletHandlers = handlers;
+    }
+
+    public boolean handle(HttpServletRequest req, HttpServletResponse res) 
throws ServletException, IOException {
+        for (ServletHandler handler : m_servletHandlers) {
+            if (handler.handle(req, res)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean hasServletsMapped() {
+        return m_servletHandlers.length > 0;
+    }
+
+    public RequestDispatcher getRequestDispatcher(String path) {
+        for (ServletHandler handler : m_servletHandlers) {
+            if (handler.matchesPath(path)) {
+                return new Dispatcher(path, handler);
+            }
+        }
+        return null;
+    }
+
+    private final class Dispatcher implements RequestDispatcher {
+
+        private final String m_path;
+        private final ServletHandler m_servletHandler;
+
+        public Dispatcher(String path, ServletHandler handler) {
+            m_path = path;
+            m_servletHandler = handler;
+        }
+
+        public void forward(ServletRequest req, ServletResponse res) throws 
ServletException, IOException {
+            if (res.isCommitted()) {
+                throw new ServletException("Response has been committed");
+            }
+            m_servletHandler.handle(new RequestWrapper((HttpServletRequest) 
req, m_path), (HttpServletResponse) res);
+        }
+
+        public void include(ServletRequest req, ServletResponse res) throws 
ServletException, IOException {
+            m_servletHandler.handle((HttpServletRequest) req, 
(HttpServletResponse) res);
+        }
+    }
+
+    private final class RequestWrapper extends HttpServletRequestWrapper {
+
+        private final String m_requestUri;
+
+        public RequestWrapper(HttpServletRequest req, String requestUri) {
+            super(req);
+            m_requestUri = requestUri;
+        }
+
+        public String getRequestURI() {
+            return m_requestUri;
+        }
+    }
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/extender/TenantParameterDispatchExtender.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/extender/TenantParameterDispatchExtender.java
 Tue Jan 25 14:25:33 2011
@@ -0,0 +1,51 @@
+package org.amdatu.web.dispatcher.extender;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+import org.amdatu.core.tenant.Tenant;
+import org.amdatu.core.tenant.TenantException;
+import org.amdatu.core.tenant.TenantManagementService;
+import org.amdatu.web.dispatcher.DispatchExtenderFilter;
+
+public final class TenantParameterDispatchExtender implements 
DispatchExtenderFilter {
+
+    public final static String TENANT_REQUESTCONTEXT_KEY = 
"org.amdatu.web.dispatcher.TENANT";
+    public final static String TENANT_REQUEST_PARAMETER = "tenant";
+
+    private TenantManagementService m_tenantManagementService;
+
+    public void setTenentManagementService(TenantManagementService 
tenantManagementService) {
+        m_tenantManagementService = tenantManagementService;
+    }
+
+    public void init(FilterConfig filterConfig) throws ServletException {
+    }
+
+    public void destroy() {
+    }
+
+    public void doFilter(ServletRequest servletRequest, ServletResponse 
servletResponse, FilterChain filterChain)
+        throws IOException,
+        ServletException {
+
+        HttpServletRequest httpServletRequest = (HttpServletRequest) 
servletRequest;
+        String tenantId = 
httpServletRequest.getParameter(TENANT_REQUEST_PARAMETER);
+        if (tenantId != null) {
+            try {
+                Tenant tenant = 
m_tenantManagementService.getTenantById(tenantId);
+                if (tenant != null) {
+                    servletRequest.setAttribute(TENANT_REQUESTCONTEXT_KEY, 
tenant);
+                }
+            }
+            catch (TenantException e) {}
+        }
+        filterChain.doFilter(servletRequest, servletResponse);
+    }
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/filter/DispatchInterceptFilter.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/filter/DispatchInterceptFilter.java
   Tue Jan 25 14:25:33 2011
@@ -0,0 +1,103 @@
+package org.amdatu.web.dispatcher.filter;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+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.HttpServletResponse;
+
+import org.amdatu.web.dispatcher.DispatcherService;
+import org.amdatu.web.dispatcher.dispatch.FilterPipeline;
+import org.osgi.service.log.LogService;
+
+/**
+ * Simple interceptor filter that collaborates with 
<code>DispatcherService</code>
+ * to redirect request to a custom (mostly tenant specific) pipeline. When 
there
+ * is no custom pipeline or no target matches the request is continued down the
+ * original chain.
+ */
+public final class DispatchInterceptFilter implements Filter {
+
+    private DispatcherService m_dispatcherService;
+    private LogService m_logService;
+    private FilterConfig m_filterConfig;
+    private boolean m_initialized = false;
+
+    public void setDispatcherService(DispatcherService dispatcherService) {
+        m_dispatcherService = dispatcherService;
+    }
+
+    public void setLogService(LogService logService) {
+        m_logService = logService;
+    }
+
+    public ServletContext getServletContext() {
+        return m_filterConfig.getServletContext();
+    }
+
+    public void init(FilterConfig filterConfig) throws ServletException {
+        if (m_initialized)
+            throw new 
IllegalStateException(DispatchInterceptFilter.class.getSimpleName() + " 
duplicate init call");
+        m_initialized = true;
+        m_filterConfig = filterConfig;
+        if (m_logService != null)
+            m_logService.log(LogService.LOG_INFO, 
DispatchInterceptFilter.class.getSimpleName() + " initialized");
+    }
+
+    public void destroy() {
+        if (m_logService != null)
+            m_logService.log(LogService.LOG_INFO, 
DispatchInterceptFilter.class.getSimpleName() + " destroyed");
+    }
+
+    public void doFilter(ServletRequest servletRequest, ServletResponse 
servletResponse, FilterChain filterChain)
+        throws IOException,
+        ServletException {
+
+        HttpServletRequest httpServletRequest = (HttpServletRequest) 
servletRequest;
+        HttpServletResponse httpServletResponse = (HttpServletResponse) 
servletResponse;
+
+        // FIXME: no excessive logging in request path
+        if (m_logService != null)
+            m_logService.log(LogService.LOG_WARNING, 
getLogMessage(httpServletRequest));
+
+        FilterPipeline filterPipeline = 
m_dispatcherService.getFilterPipeline(httpServletRequest);
+        if (filterPipeline != null) {
+
+            // Standard behavior: invoke the custom chain that falls
+            // back to the normal http service chain when no servlet
+            // handles the request.
+            filterPipeline.dispatch(httpServletRequest, httpServletResponse,
+                filterChain);
+            return;
+        }
+
+        // Fallback behavior: if we have no custom chain we just
+        // continue the normal http service chain.
+        filterChain.doFilter(servletRequest, servletResponse);
+    }
+
+    private String getLogMessage(HttpServletRequest httpServletRequest) {
+        StringBuilder sb = new StringBuilder("Intercepted request: ");
+        sb.append(httpServletRequest.getScheme());
+        sb.append("://");
+        sb.append(httpServletRequest.getServerName());
+        if (httpServletRequest.getServerPort() != -1 && 
httpServletRequest.getServerPort() != 80) {
+            sb.append(":");
+            sb.append(httpServletRequest.getServerPort());
+        }
+        if (httpServletRequest.getPathInfo() != null) {
+            sb.append(httpServletRequest.getPathInfo());
+        }
+        if (httpServletRequest.getQueryString() != null) {
+            sb.append("?");
+            sb.append(httpServletRequest.getQueryString());
+        }
+        return sb.toString();
+    }
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/AbstractHandler.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/AbstractHandler.java
  Tue Jan 25 14:25:33 2011
@@ -0,0 +1,64 @@
+package org.amdatu.web.dispatcher.handler;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.servlet.ServletException;
+
+import org.amdatu.web.dispatcher.context.ExtServletContext;
+
+public abstract class AbstractHandler {
+
+    private final static AtomicInteger ID =
+        new AtomicInteger();
+
+    private final String m_handlerId;
+    private final ExtServletContext m_servletContext;
+    private final Map<String, String> m_initParams;
+    private final String m_tenantid;
+
+    public AbstractHandler(ExtServletContext context, String tenantid) {
+        m_handlerId = "" + ID.incrementAndGet();
+        m_servletContext = context;
+        m_initParams = new HashMap<String, String>();
+        m_tenantid = tenantid;
+    }
+
+    public final String getId() {
+        return m_handlerId;
+    }
+
+    public final String getTenantId() {
+        return m_tenantid;
+    }
+
+    protected final ExtServletContext getContext() {
+        return m_servletContext;
+    }
+
+    public final Map<String, String> getInitParams() {
+        return m_initParams;
+    }
+
+    public final void setInitParams(Dictionary<String, String> map) {
+        m_initParams.clear();
+        if (map == null) {
+            return;
+        }
+        Enumeration<String> e = map.keys();
+        while (e.hasMoreElements()) {
+            Object key = e.nextElement();
+            Object value = map.get(key);
+            if ((key instanceof String) && (value instanceof String)) {
+                this.m_initParams.put((String) key, (String) value);
+            }
+        }
+    }
+
+    public abstract void init() throws ServletException;
+
+    public abstract void destroy();
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/AbstractHandlerRegistry.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/AbstractHandlerRegistry.java
  Tue Jan 25 14:25:33 2011
@@ -0,0 +1,78 @@
+package org.amdatu.web.dispatcher.handler;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import javax.servlet.ServletContext;
+
+import org.amdatu.web.dispatcher.DispatcherService;
+import org.amdatu.web.dispatcher.context.DefaultHttpContext;
+import org.amdatu.web.dispatcher.service.DispatcherServiceImpl;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.log.LogService;
+
+public abstract class AbstractHandlerRegistry {
+
+    private DispatcherService m_dispatcherService;
+
+    public AbstractHandlerRegistry(DispatcherService dispatcherService) {
+        m_dispatcherService = dispatcherService;
+    }
+
+    protected DispatcherService getDispatcherService() {
+        return m_dispatcherService;
+    }
+
+    protected LogService getLogService() {
+        return m_dispatcherService.getLogService();
+    }
+
+    protected ServletContext getServletContext() {
+        return m_dispatcherService.getServletContext();
+    }
+
+    protected String getStringProperty(ServiceReference ref, String key) {
+        Object value = ref.getProperty(key);
+        return (value instanceof String) ? (String) value : null;
+    }
+
+    protected int getIntProperty(ServiceReference ref, String key, int 
defValue) {
+        Object value = ref.getProperty(key);
+        if (value == null) {
+            return defValue;
+        }
+        try {
+            return Integer.parseInt(value.toString());
+        }
+        catch (Exception e) {
+            return defValue;
+        }
+    }
+
+    protected Dictionary<String, String> getInitParams(ServiceReference 
serviceReference) {
+        Dictionary<String, String> initParams = new Hashtable<String, 
String>();
+        for (String key : serviceReference.getPropertyKeys()) {
+            if (key.startsWith(DispatcherServiceImpl.INIT_KEY_PREFIX)) {
+                String paramKey = 
key.substring(DispatcherServiceImpl.INIT_KEY_PREFIX.length());
+                String paramValue = getStringProperty(serviceReference, key);
+                if (paramValue != null) {
+                    initParams.put(paramKey, paramValue);
+                }
+            }
+        }
+        return initParams;
+    }
+
+    protected HttpContext getHttpContext(ServiceReference serviceReference) {
+        Bundle bundle = serviceReference.getBundle();
+        String contextId = getStringProperty(serviceReference, 
DispatcherServiceImpl.CONTEXT_ID_KEY);
+        if (contextId != null) {
+            return 
m_dispatcherService.getHttpContextManager().getHttpContext(bundle, contextId);
+        }
+        else {
+            return new DefaultHttpContext(bundle);
+        }
+    }
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/FilterConfigImpl.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/FilterConfigImpl.java
 Tue Jan 25 14:25:33 2011
@@ -0,0 +1,37 @@
+package org.amdatu.web.dispatcher.handler;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Map;
+
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+
+public final class FilterConfigImpl implements FilterConfig {
+
+    private final String m_name;
+    private final ServletContext m_servletcontext;
+    private final Map<String, String> m_initParams;
+
+    public FilterConfigImpl(String name, ServletContext context, Map<String, 
String> initParams) {
+        m_name = name;
+        m_servletcontext = context;
+        m_initParams = initParams;
+    }
+
+    public String getFilterName() {
+        return m_name;
+    }
+
+    public ServletContext getServletContext() {
+        return m_servletcontext;
+    }
+
+    public String getInitParameter(String name) {
+        return m_initParams.get(name);
+    }
+
+    public Enumeration<String> getInitParameterNames() {
+        return Collections.enumeration(m_initParams.keySet());
+    }
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/FilterHandler.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/FilterHandler.java
    Tue Jan 25 14:25:33 2011
@@ -0,0 +1,79 @@
+package org.amdatu.web.dispatcher.handler;
+
+import java.io.IOException;
+import java.util.regex.Pattern;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.amdatu.web.dispatcher.context.ExtServletContext;
+
+public final class FilterHandler extends AbstractHandler implements 
Comparable<FilterHandler> {
+
+    private final FilterHandlerRegistry m_filterHandlerRegistry;
+    private final Filter m_filter;
+    private final Pattern m_pattern;
+    private final int m_ranking;
+
+    public FilterHandler(FilterHandlerRegistry filterHandlerRegistry, 
ExtServletContext context, Filter filter,
+        String pattern, int ranking, String tenantid) {
+        super(context, tenantid);
+        m_filterHandlerRegistry = filterHandlerRegistry;
+        m_filter = filter;
+        m_ranking = ranking;
+        m_pattern = Pattern.compile(pattern);
+    }
+
+    public Filter getFilter() {
+        return m_filter;
+    }
+
+    public void init()
+        throws ServletException {
+        String name = "filter_" + getId();
+        FilterConfig config = new FilterConfigImpl(name, getContext(), 
getInitParams());
+        m_filter.init(config);
+    }
+
+    public void destroy() {
+        m_filter.destroy();
+    }
+
+    public void handle(HttpServletRequest httpServletRequest, 
HttpServletResponse httpServletResponse,
+        FilterChain filterChain) throws ServletException, IOException {
+        boolean matches = matchesPath(httpServletRequest.getPathInfo());
+        if (matches) {
+            matches = m_filterHandlerRegistry.filterHandlerMatches(this, 
httpServletRequest);
+            if (matches) {
+                doHandle(httpServletRequest, httpServletResponse, filterChain);
+                return;
+            }
+        }
+        filterChain.doFilter(httpServletRequest, httpServletResponse);
+    }
+
+    public boolean matchesPath(String uri) {
+        if (uri == null) {
+            uri = "/";
+        }
+        return m_pattern.matcher(uri).matches();
+    }
+
+    public int compareTo(FilterHandler other) {
+        return other.m_ranking - m_ranking;
+    }
+
+    private void doHandle(HttpServletRequest req, HttpServletResponse res, 
FilterChain chain)
+        throws ServletException, IOException {
+        if (!getContext().handleSecurity(req, res)) {
+            res.sendError(HttpServletResponse.SC_FORBIDDEN);
+        }
+        else {
+            m_filter.doFilter(req, res, chain);
+        }
+    }
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/FilterHandlerRegistry.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/FilterHandlerRegistry.java
    Tue Jan 25 14:25:33 2011
@@ -0,0 +1,119 @@
+package org.amdatu.web.dispatcher.handler;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.Filter;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+
+import org.amdatu.web.dispatcher.DispatchFilterMatcher;
+import org.amdatu.web.dispatcher.DispatcherService;
+import org.amdatu.web.dispatcher.context.HandlerServletContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+public final class FilterHandlerRegistry extends AbstractHandlerRegistry {
+
+    private final Map<ServiceReference, FilterHandler> m_filterHandlers =
+        new HashMap<ServiceReference, FilterHandler>();
+
+    private final Map<Filter, FilterHandler> m_extenderFilterHandlers = new 
HashMap<Filter, FilterHandler>();
+    private Set<DispatchFilterMatcher> m_matchers = new 
HashSet<DispatchFilterMatcher>();
+
+    public FilterHandlerRegistry(DispatcherService dispatcherService) {
+        super(dispatcherService);
+    }
+
+    public void addDispatchFilterMatcher(DispatchFilterMatcher 
dispatchFilterMatcher) {
+        if (m_matchers.contains(dispatchFilterMatcher)) {
+            throw new IllegalStateException("unforseen duplicate matcher....");
+        }
+        m_matchers.add(dispatchFilterMatcher);
+    }
+
+    public void removeDispatchFilterMatcher(DispatchFilterMatcher 
dispatchFilterMatcher) {
+        if (!m_matchers.contains(dispatchFilterMatcher)) {
+            throw new IllegalStateException("unforseen unknown matcher....");
+        }
+        m_matchers.remove(dispatchFilterMatcher);
+    }
+
+    public void addDispatchExtenderFilter(FilterHandler handler)
+        throws ServletException {
+        if (m_extenderFilterHandlers.containsKey(handler.getFilter())) {
+            throw new IllegalStateException("unforseen duplicate 
extender....");
+        }
+
+        handler.init();
+        m_extenderFilterHandlers.put(handler.getFilter(), handler);
+    }
+
+    public void removeDispatchExtenderFilter(Filter filter) {
+        if (!m_extenderFilterHandlers.containsKey(filter)) {
+            throw new IllegalStateException("unforseen unknown extender....");
+        }
+        FilterHandler handler = m_extenderFilterHandlers.remove(filter);
+        if (handler != null) {
+            handler.destroy();
+        }
+    }
+
+    public void addFilterHandler(ServiceReference serviceReference, Filter 
filter) {
+        if (m_filterHandlers.containsKey(serviceReference)) {
+            throw new IllegalStateException("Unexpected.... ");
+        }
+        int ranking = getIntProperty(serviceReference, 
Constants.SERVICE_RANKING, 0);
+        String pattern = getStringProperty(serviceReference, 
DispatcherService.PATTERN_KEY);
+        if (pattern == null) {
+            return;
+        }
+
+        String tenant = getStringProperty(serviceReference, "tenant_id");
+
+        HandlerServletContext extServletContextWrapper =
+            new HandlerServletContext(getServletContext(), 
getHttpContext(serviceReference));
+        FilterHandler filterHandler =
+            new FilterHandler(this, extServletContextWrapper, filter, pattern, 
ranking, tenant);
+        filterHandler.setInitParams(getInitParams(serviceReference));
+
+        m_filterHandlers.put(serviceReference, filterHandler);
+    }
+
+    public void removeFilterHandler(ServiceReference serviceReference, Filter 
filter) {
+        if (!m_filterHandlers.containsKey(serviceReference)) {
+            throw new IllegalStateException("Unexpected.... ");
+        }
+        FilterHandler filterHandler = 
m_filterHandlers.remove(serviceReference);
+        if (filterHandler != null) {
+            filterHandler.destroy();
+        }
+    }
+
+    public FilterHandler[] getFilterHandlers(HttpServletRequest 
httpServletRequest) {
+        // FIXME optimize
+        FilterHandler[] filterHandlers = m_filterHandlers.values().toArray(new 
FilterHandler[m_filterHandlers.size()]);
+        Arrays.sort(filterHandlers);
+        FilterHandler[] extenderFilterHandlers =
+            m_extenderFilterHandlers.values().toArray(new 
FilterHandler[m_extenderFilterHandlers.size()]);
+        Arrays.sort(filterHandlers);
+        FilterHandler[] finalFilterHandlers = new 
FilterHandler[filterHandlers.length + extenderFilterHandlers.length];
+        System.arraycopy(extenderFilterHandlers, 0, finalFilterHandlers, 0, 
extenderFilterHandlers.length);
+        System.arraycopy(filterHandlers, 0, finalFilterHandlers, 
extenderFilterHandlers.length, filterHandlers.length);
+
+        System.err.println("Number of matching filters: " + 
filterHandlers.length);
+        return finalFilterHandlers;
+    }
+
+    public boolean filterHandlerMatches(FilterHandler filterHandler, 
HttpServletRequest httpServletRequest) {
+        for (DispatchFilterMatcher matcher : m_matchers) {
+            if (!matcher.matches(filterHandler, httpServletRequest)) {
+                return false;
+            }
+        }
+        return true;
+    }
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/ServletConfigImpl.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/ServletConfigImpl.java
        Tue Jan 25 14:25:33 2011
@@ -0,0 +1,37 @@
+package org.amdatu.web.dispatcher.handler;
+
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.Map;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+
+public final class ServletConfigImpl implements ServletConfig {
+
+    private final String m_name;
+    private final ServletContext m_servletContext;
+    private final Map<String, String> m_initParams;
+
+    public ServletConfigImpl(String name, ServletContext context, Map<String, 
String> initParams) {
+        m_name = name;
+        m_servletContext = context;
+        m_initParams = initParams;
+    }
+
+    public String getServletName() {
+        return m_name;
+    }
+
+    public ServletContext getServletContext() {
+        return m_servletContext;
+    }
+
+    public String getInitParameter(String name) {
+        return m_initParams.get(name);
+    }
+
+    public Enumeration<String> getInitParameterNames() {
+        return Collections.enumeration(m_initParams.keySet());
+    }
+}
\ No newline at end of file

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/ServletHandler.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/ServletHandler.java
   Tue Jan 25 14:25:33 2011
@@ -0,0 +1,85 @@
+package org.amdatu.web.dispatcher.handler;
+
+import java.io.IOException;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.amdatu.web.dispatcher.context.ExtServletContext;
+
+public final class ServletHandler extends AbstractHandler implements 
Comparable<ServletHandler> {
+
+    private final ServletHandlerRegistry m_servletHandlerRegistry;
+    private final String m_alias;
+    private final Servlet m_servlet;
+
+    public ServletHandler(ServletHandlerRegistry servletHandlerRegistry, 
ExtServletContext context, Servlet servlet,
+        String alias, String tenantid) {
+        super(context, tenantid);
+        m_servletHandlerRegistry = servletHandlerRegistry;
+        m_alias = alias;
+        m_servlet = servlet;
+    }
+
+    public String getAlias() {
+        return m_alias;
+    }
+
+    public Servlet getServlet() {
+        return m_servlet;
+    }
+
+    public void init() throws ServletException {
+        String name = "servlet_" + getId();
+        ServletConfig config = new ServletConfigImpl(name, getContext(), 
getInitParams());
+        m_servlet.init(config);
+    }
+
+    public void destroy() {
+        this.m_servlet.destroy();
+    }
+
+    public boolean handle(HttpServletRequest httpServletRequest, 
HttpServletResponse httpServletResponse)
+        throws ServletException, IOException {
+
+        boolean matches = matchesPath(httpServletRequest.getPathInfo());
+        if (matches) {
+            if (m_servletHandlerRegistry.servletHandlerMatches(this, 
httpServletRequest)) {
+                doHandle(httpServletRequest, httpServletResponse);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean matchesPath(String uri) {
+        if (uri == null) {
+            return m_alias.equals("/");
+        }
+        else if (m_alias.equals("/")) {
+            return uri.startsWith(m_alias);
+        }
+        else {
+            return uri.equals(m_alias) || uri.startsWith(m_alias + "/");
+        }
+    }
+
+    public int compareTo(ServletHandler other) {
+        return other.m_alias.length() - m_alias.length();
+    }
+
+    private void doHandle(HttpServletRequest httpServletRequest, 
HttpServletResponse httpServletResponse)
+        throws ServletException, IOException {
+        if (!getContext().handleSecurity(httpServletRequest, 
httpServletResponse)) {
+            if (!httpServletResponse.isCommitted()) {
+                
httpServletResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
+            }
+        }
+        else {
+            m_servlet.service(new ServletHandlerRequest(httpServletRequest, 
m_alias), httpServletResponse);
+        }
+    }
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/ServletHandlerRegistry.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/ServletHandlerRegistry.java
   Tue Jan 25 14:25:33 2011
@@ -0,0 +1,95 @@
+package org.amdatu.web.dispatcher.handler;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.Servlet;
+import javax.servlet.http.HttpServletRequest;
+
+import org.amdatu.web.dispatcher.DispatchServletMatcher;
+import org.amdatu.web.dispatcher.DispatcherService;
+import org.amdatu.web.dispatcher.context.HandlerServletContext;
+import org.amdatu.web.dispatcher.service.DispatcherServiceImpl;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+
+//FIXME synchronization
+public final class ServletHandlerRegistry extends AbstractHandlerRegistry {
+
+    private final Map<ServiceReference, ServletHandler> m_servletHandlers =
+        new HashMap<ServiceReference, ServletHandler>();
+
+    private Set<DispatchServletMatcher> m_matchers = new 
HashSet<DispatchServletMatcher>();
+
+    public ServletHandlerRegistry(DispatcherService dispatcherService) {
+        super(dispatcherService);
+    }
+
+    public void addDispatchServletMatcher(DispatchServletMatcher 
dispatchServletMatcher) {
+        if (m_matchers.contains(dispatchServletMatcher)) {
+            throw new IllegalStateException("unforseen duplicate matcher....");
+        }
+        m_matchers.add(dispatchServletMatcher);
+    }
+
+    public void removeDispatchServletMatcher(DispatchServletMatcher 
dispatchServletMatcher) {
+        if (!m_matchers.contains(dispatchServletMatcher)) {
+            throw new IllegalStateException("unforseen unknown matcher....");
+        }
+        m_matchers.remove(dispatchServletMatcher);
+    }
+
+    public void addServletHandler(ServiceReference serviceReference, Servlet 
servlet) {
+        if (m_servletHandlers.containsKey(serviceReference)) {
+            throw new IllegalStateException("Unexpected.... ");
+        }
+
+        String alias = getStringProperty(serviceReference, 
DispatcherServiceImpl.ALIAS_KEY);
+        if (alias == null) {
+            if (getLogService() != null)
+                getLogService().log(LogService.LOG_WARNING, "Cannot register a 
servlet without alias");
+            return;
+        }
+
+        String tenant = getStringProperty(serviceReference, "tenant_id");
+
+        HandlerServletContext servletContextWrapper =
+            new HandlerServletContext(getServletContext(), 
getHttpContext(serviceReference));
+
+        ServletHandler handler = new ServletHandler(this, 
servletContextWrapper, servlet, alias, tenant);
+        handler.setInitParams(getInitParams(serviceReference));
+
+        m_servletHandlers.put(serviceReference, handler);
+    }
+
+    public void removeServletHandler(ServiceReference serviceReference, 
Servlet servlet) {
+        if (!m_servletHandlers.containsKey(serviceReference)) {
+            return;
+        }
+        ServletHandler servletHandler = 
m_servletHandlers.remove(serviceReference);
+        if (servletHandler != null) {
+            servletHandler.destroy();
+        }
+    }
+
+    public ServletHandler[] getServletHandlers(HttpServletRequest 
httpServletRequest) {
+        ServletHandler[] servletHandlers =
+            m_servletHandlers.values().toArray(new 
ServletHandler[m_servletHandlers.size()]);
+        Arrays.sort(servletHandlers);
+
+        System.err.println("Number of matching servlets: " + 
servletHandlers.length);
+        return servletHandlers;
+    }
+
+    public boolean servletHandlerMatches(ServletHandler servletHandler, 
HttpServletRequest httpServletRequest) {
+        for (DispatchServletMatcher matcher : m_matchers) {
+            if (!matcher.matches(servletHandler, httpServletRequest)) {
+                return false;
+            }
+        }
+        return true;
+    }
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/ServletHandlerRequest.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/handler/ServletHandlerRequest.java
    Tue Jan 25 14:25:33 2011
@@ -0,0 +1,91 @@
+package org.amdatu.web.dispatcher.handler;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+import org.osgi.service.http.HttpContext;
+
+final class ServletHandlerRequest extends HttpServletRequestWrapper {
+
+    private final String m_alias;
+    private String m_contextPath;
+    private String m_pathInfo;
+    private boolean m_pathInfoCalculated = false;
+
+    public ServletHandlerRequest(HttpServletRequest req, String alias) {
+        super(req);
+        m_alias = alias;
+    }
+
+    @Override
+    public String getAuthType() {
+        String authType = (String) 
getAttribute(HttpContext.AUTHENTICATION_TYPE);
+        if (authType != null) {
+            return authType;
+        }
+        return super.getAuthType();
+    }
+
+    @Override
+    public String getContextPath() {
+        if (m_contextPath == null) {
+            final String context = super.getContextPath();
+            final String servlet = super.getServletPath();
+            if (context.length() == 0) {
+                m_contextPath = servlet;
+            }
+            else if (servlet.length() == 0) {
+                m_contextPath = context;
+            }
+            else {
+                m_contextPath = context + servlet;
+            }
+        }
+        return m_contextPath;
+    }
+
+    @Override
+    public String getPathInfo() {
+        if (!m_pathInfoCalculated) {
+            m_pathInfo = calculatePathInfo();
+            m_pathInfoCalculated = true;
+        }
+        return m_pathInfo;
+    }
+
+    @Override
+    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 String getServletPath() {
+        if ("/".equals(m_alias)) {
+            return "";
+        }
+        return m_alias;
+    }
+
+    private String calculatePathInfo() {
+        String pathInfo = super.getPathInfo();
+        if (pathInfo != null) {
+            if (!"/".equals(m_alias)) {
+                pathInfo = pathInfo.substring(m_alias.length());
+            }
+            if (pathInfo.length() == 0) {
+                pathInfo = null;
+            }
+        }
+        return pathInfo;
+    }
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/matcher/TenantAwareServletMatcher.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/matcher/TenantAwareServletMatcher.java
        Tue Jan 25 14:25:33 2011
@@ -0,0 +1,20 @@
+package org.amdatu.web.dispatcher.matcher;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.amdatu.core.tenant.Tenant;
+import org.amdatu.web.dispatcher.DispatchServletMatcher;
+import org.amdatu.web.dispatcher.extender.TenantParameterDispatchExtender;
+import org.amdatu.web.dispatcher.handler.ServletHandler;
+
+public class TenantAwareServletMatcher implements DispatchServletMatcher {
+
+    public boolean matches(ServletHandler servletHandler, HttpServletRequest 
httpServletRequest) {
+        if (servletHandler.getTenantId() == null || 
servletHandler.getTenantId() == "") {
+            return true;
+        }
+        Tenant tenant =
+            (Tenant) 
httpServletRequest.getAttribute(TenantParameterDispatchExtender.TENANT_REQUESTCONTEXT_KEY);
+        return (tenant != null && 
servletHandler.getTenantId().equals(tenant.getId()));
+    }
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/matcher/TenantUnawareServletMatcher.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/matcher/TenantUnawareServletMatcher.java
      Tue Jan 25 14:25:33 2011
@@ -0,0 +1,13 @@
+package org.amdatu.web.dispatcher.matcher;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.amdatu.web.dispatcher.DispatchServletMatcher;
+import org.amdatu.web.dispatcher.handler.ServletHandler;
+
+public class TenantUnawareServletMatcher implements DispatchServletMatcher {
+
+    public boolean matches(ServletHandler servletHandler, HttpServletRequest 
httpServletRequest) {
+        return (servletHandler.getTenantId() == null || 
servletHandler.getTenantId().equals(""));
+    }
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/osgi/DispatcherServiceActivator.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/osgi/DispatcherServiceActivator.java
  Tue Jan 25 14:25:33 2011
@@ -0,0 +1,79 @@
+/*
+    Copyright (C) 2010 Amdatu.org
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.web.dispatcher.osgi;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import javax.servlet.Filter;
+import javax.servlet.Servlet;
+
+import org.amdatu.core.tenant.Tenant;
+import org.amdatu.core.tenant.TenantManagementService;
+import org.amdatu.web.dispatcher.DispatcherService;
+import org.amdatu.web.dispatcher.service.DispatcherServiceImpl;
+import org.amdatu.web.dispatcher.test.HelloWorldServlet;
+import org.apache.felix.dm.DependencyActivatorBase;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.http.api.ExtHttpService;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.log.LogService;
+
+public final class DispatcherServiceActivator extends DependencyActivatorBase {
+
+    @Override
+    public void init(BundleContext context, DependencyManager manager) throws 
Exception {
+
+        Dictionary<String, Object> serviceProperties = new Hashtable<String, 
Object>();
+        manager.add(
+                createComponent()
+                    .setInterface(DispatcherService.class.getName(), 
serviceProperties)
+                    .setImplementation(DispatcherServiceImpl.class)
+                    
.add(createServiceDependency().setService(ExtHttpService.class).setRequired(true))
+                    
.add(createServiceDependency().setService(LogService.class).setRequired(true))
+                    
.add(createServiceDependency().setService(TenantManagementService.class).setRequired(true))
+                    .add(
+                        createServiceDependency()
+                            .setService(HttpContext.class)
+                            .setCallbacks("addHttpContext", 
"removeHttpContext")
+                            .setRequired(false))
+                    .add(
+                        createServiceDependency()
+                            .setService(Servlet.class)
+                            .setCallbacks("addServlet", "removeServlet")
+                            .setRequired(false))
+                    .add(
+                        createServiceDependency()
+                            .setService(Filter.class)
+                            .setCallbacks("addFilter", "removeFilter")
+                            .setRequired(false))
+                );
+
+        // test servlets
+        Dictionary<String, String> props = new Hashtable<String, String>();
+        props.put("alias", "/hello/world");
+        manager.add(
+            createAdapterService(Tenant.class, null)
+                .setImplementation(HelloWorldServlet.class)
+                .setInterface(Servlet.class.getName(), props));
+    }
+
+    @Override
+    public void destroy(BundleContext context, DependencyManager manager) 
throws Exception {
+    }
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/service/DispatcherServiceImpl.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/service/DispatcherServiceImpl.java
    Tue Jan 25 14:25:33 2011
@@ -0,0 +1,176 @@
+/*
+    Copyright (C) 2010 Amdatu.org
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.amdatu.web.dispatcher.service;
+
+import java.util.Hashtable;
+
+import javax.servlet.Filter;
+import javax.servlet.Servlet;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+
+import org.amdatu.core.tenant.TenantManagementService;
+import org.amdatu.web.dispatcher.DispatcherService;
+import org.amdatu.web.dispatcher.context.DefaultHttpContext;
+import org.amdatu.web.dispatcher.context.HandlerServletContext;
+import org.amdatu.web.dispatcher.context.HttpContextManager;
+import org.amdatu.web.dispatcher.dispatch.FilterPipeline;
+import org.amdatu.web.dispatcher.dispatch.ServletPipeline;
+import org.amdatu.web.dispatcher.extender.TenantParameterDispatchExtender;
+import org.amdatu.web.dispatcher.filter.DispatchInterceptFilter;
+import org.amdatu.web.dispatcher.handler.FilterHandler;
+import org.amdatu.web.dispatcher.handler.FilterHandlerRegistry;
+import org.amdatu.web.dispatcher.handler.ServletHandlerRegistry;
+import org.amdatu.web.dispatcher.matcher.TenantAwareServletMatcher;
+import org.apache.felix.http.api.ExtHttpService;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.log.LogService;
+
+public class DispatcherServiceImpl implements DispatcherService {
+
+    private volatile BundleContext m_bundleContext;
+    private volatile LogService m_logService;
+    private volatile ExtHttpService m_httpService;
+    private volatile TenantManagementService m_tenantManagementService;
+
+    private DispatchInterceptFilter m_interceptorFilter;
+    private HttpContextManager m_httpContextManager;
+    private ServletHandlerRegistry m_servletHandlerRegistry;
+    private FilterHandlerRegistry m_filterHandlerRegistry;
+
+    private ServletContext m_extServletContext;
+
+    public void init() {
+        if (m_logService != null)
+            m_logService.log(LogService.LOG_INFO, 
DispatcherServiceImpl.class.getSimpleName() + " initialized");
+    }
+
+    public void destroy() {
+        if (m_logService != null)
+            m_logService.log(LogService.LOG_INFO, 
DispatcherServiceImpl.class.getSimpleName() + " destroyed");
+    }
+
+    public void start() throws Exception {
+
+        // tmp should be service regs
+        m_servletHandlerRegistry = new ServletHandlerRegistry(this);
+        m_servletHandlerRegistry.addDispatchServletMatcher(new 
TenantAwareServletMatcher());
+
+        // tmp should be service regs
+        m_filterHandlerRegistry = new FilterHandlerRegistry(this);
+        HandlerServletContext extServletContextWrapper =
+            new HandlerServletContext(m_extServletContext, new 
DefaultHttpContext(m_bundleContext.getBundle()));
+        TenantParameterDispatchExtender tde = new 
TenantParameterDispatchExtender();
+        tde.setTenentManagementService(m_tenantManagementService);
+        FilterHandler handler =
+            new FilterHandler(m_filterHandlerRegistry, 
extServletContextWrapper, tde, ".*", 0, null);
+        handler.setInitParams(null);
+        m_filterHandlerRegistry.addDispatchExtenderFilter(handler);
+
+        m_httpContextManager = new HttpContextManager();
+
+        m_interceptorFilter = new DispatchInterceptFilter();
+        m_interceptorFilter.setLogService(m_logService);
+        m_interceptorFilter.setDispatcherService(this);
+        try {
+            m_httpService.registerFilter(m_interceptorFilter, ".*", new 
Hashtable<String, Object>(), 0,
+                new DefaultHttpContext(m_bundleContext.getBundle()));
+            m_extServletContext = m_interceptorFilter.getServletContext();
+        }
+        catch (ServletException e) {
+            throw new Exception(DispatcherServiceImpl.class.getSimpleName() + 
" failed to start", e);
+        }
+        m_logService.log(LogService.LOG_INFO, 
DispatcherServiceImpl.class.getSimpleName() + " started");
+    }
+
+    public void stop() {
+        m_logService.log(LogService.LOG_ERROR, "stop");
+
+        m_httpContextManager = null;
+
+        m_httpService.unregister(".*");
+        m_interceptorFilter.setDispatcherService(null);
+        m_interceptorFilter.setLogService(null);
+        m_interceptorFilter = null;
+
+        m_logService.log(LogService.LOG_INFO, 
DispatcherServiceImpl.class.getSimpleName() + " stopped");
+    }
+
+    public void addHttpContext(ServiceReference serviceReference, Object 
service) {
+        HttpContext httpContext = (HttpContext) service;
+        Bundle bundle = serviceReference.getBundle();
+        String contextId = getStringProperty(serviceReference, CONTEXT_ID_KEY);
+        if (contextId != null) {
+            m_httpContextManager.addHttpContext(bundle, contextId, 
httpContext);
+        }
+    }
+
+    public void removeHttpContext(ServiceReference serviceReference, Object 
service) {
+        HttpContext httpContext = (HttpContext) service;
+        m_httpContextManager.removeHttpContext(httpContext);
+    }
+
+    public void addServlet(ServiceReference serviceReference, Object service) {
+        Servlet servlet = (Servlet) service;
+        m_servletHandlerRegistry.addServletHandler(serviceReference, servlet);
+    }
+
+    public void removeServlet(ServiceReference serviceReference, Object 
service) {
+        Servlet servlet = (Servlet) service;
+        m_servletHandlerRegistry.removeServletHandler(serviceReference, 
servlet);
+    }
+
+    public void addFilter(ServiceReference serviceReference, Object service) {
+        Filter filter = (Filter) service;
+        m_filterHandlerRegistry.addFilterHandler(serviceReference, filter);
+    }
+
+    public void removeFilter(ServiceReference serviceReference, Object 
service) {
+        Filter filter = (Filter) service;
+        m_filterHandlerRegistry.removeFilterHandler(serviceReference, filter);
+    }
+
+    public FilterPipeline getFilterPipeline(HttpServletRequest 
httpServletRequest) {
+        ServletPipeline servletPipeline =
+            new 
ServletPipeline(m_servletHandlerRegistry.getServletHandlers(httpServletRequest));
+        FilterPipeline filterPipeline =
+            new 
FilterPipeline(m_filterHandlerRegistry.getFilterHandlers(httpServletRequest),
+                servletPipeline);
+        return filterPipeline;
+    }
+
+    private String getStringProperty(ServiceReference ref, String key) {
+        Object value = ref.getProperty(key);
+        return (value instanceof String) ? (String) value : null;
+    }
+
+    public HttpContextManager getHttpContextManager() {
+        return m_httpContextManager;
+    }
+
+    public LogService getLogService() {
+        return m_logService;
+    }
+
+    public ServletContext getServletContext() {
+        return m_extServletContext;
+    }
+}

Added: 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/test/HelloWorldServlet.java
==============================================================================
--- (empty file)
+++ 
sandbox/bdekruijff/dispatcher/src/main/java/org/amdatu/web/dispatcher/test/HelloWorldServlet.java
   Tue Jan 25 14:25:33 2011
@@ -0,0 +1,47 @@
+package org.amdatu.web.dispatcher.test;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletResponse;
+
+import org.amdatu.core.tenant.Tenant;
+
+public class HelloWorldServlet extends HttpServlet {
+
+    private Tenant m_tenant;
+
+    public void destroy() {
+        // TODO Auto-generated method stub
+
+    }
+
+    public ServletConfig getServletConfig() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public String getServletInfo() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    public void init(ServletConfig arg0) throws ServletException {
+        // TODO Auto-generated method stub
+
+    }
+
+    public void service(ServletRequest servletRequest, ServletResponse 
servletResponse) throws ServletException,
+        IOException {
+        // default behaviour
+        HttpServletResponse httpServletResponse = (HttpServletResponse) 
servletResponse;
+        PrintWriter writer = httpServletResponse.getWriter();
+        writer.append("Hello World by tenant " + m_tenant.getName());
+        writer.close();
+    }
+}

Reply via email to