tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cos...@apache.org
Subject svn commit: r433260 [3/5] - in /tomcat/sandbox/tomcat-lite: ./ java/org/apache/coyote/ java/org/apache/tomcat/lite/ java/org/apache/tomcat/lite/ctxmap/ java/org/apache/tomcat/lite/http/ java/org/apache/tomcat/lite/jmx/ java/org/apache/tomcat/lite/servl...
Date Mon, 21 Aug 2006 15:20:46 GMT
Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletRequestWrapperImpl.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletRequestWrapperImpl.java?rev=433260&r1=433259&r2=433260&view=diff
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletRequestWrapperImpl.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletRequestWrapperImpl.java Mon Aug 21 08:20:40 2006
@@ -31,14 +31,12 @@
 import javax.servlet.http.HttpServletRequestWrapper;
 import javax.servlet.http.HttpSession;
 
+import org.apache.tomcat.servlets.session.HttpSessionImpl;
+import org.apache.tomcat.servlets.session.SessionManagerServlet;
 import org.apache.tomcat.servlets.util.Enumerator;
 import org.apache.tomcat.servlets.util.RequestUtil;
 import org.apache.tomcat.util.res.StringManager;
 
-//import org.apache.catalina.Globals;
-//import org.apache.catalina.util.RequestUtil;
-//import org.apache.tomcat.util.res.StringManager;
-
 
 /**
  * Wrapper around a <code>javax.servlet.http.HttpServletRequest</code>
@@ -54,10 +52,8 @@
  *
  * @author Craig R. McClanahan
  * @author Remy Maucherat
- * @version $Revision: 303799 $ $Date: 2005-03-25 00:41:23 -0800 (Fri, 25 Mar 2005) $
  */
-
-class ServletRequestWrapperImpl extends HttpServletRequestWrapper {
+public class ServletRequestWrapperImpl extends HttpServletRequestWrapper {
 
 
     // ------------------------------------------------------- Static Variables
@@ -67,18 +63,23 @@
      * The set of attribute names that are special for request dispatchers.
      */
     protected static final String specials[] =
-    { ServletRequestImpl.INCLUDE_REQUEST_URI_ATTR, ServletRequestImpl.INCLUDE_CONTEXT_PATH_ATTR,
-      ServletRequestImpl.INCLUDE_SERVLET_PATH_ATTR, ServletRequestImpl.INCLUDE_PATH_INFO_ATTR,
-      ServletRequestImpl.INCLUDE_QUERY_STRING_ATTR, ServletRequestImpl.FORWARD_REQUEST_URI_ATTR, 
-      ServletRequestImpl.FORWARD_CONTEXT_PATH_ATTR, ServletRequestImpl.FORWARD_SERVLET_PATH_ATTR, 
-      ServletRequestImpl.FORWARD_PATH_INFO_ATTR, ServletRequestImpl.FORWARD_QUERY_STRING_ATTR };
+    { RequestDispatcherImpl.INCLUDE_REQUEST_URI_ATTR, 
+      RequestDispatcherImpl.INCLUDE_CONTEXT_PATH_ATTR,
+      RequestDispatcherImpl.INCLUDE_SERVLET_PATH_ATTR, 
+      RequestDispatcherImpl.INCLUDE_PATH_INFO_ATTR,
+      RequestDispatcherImpl.INCLUDE_QUERY_STRING_ATTR, 
+      RequestDispatcherImpl.FORWARD_REQUEST_URI_ATTR, 
+      RequestDispatcherImpl.FORWARD_CONTEXT_PATH_ATTR, 
+      RequestDispatcherImpl.FORWARD_SERVLET_PATH_ATTR, 
+      RequestDispatcherImpl.FORWARD_PATH_INFO_ATTR, 
+      RequestDispatcherImpl.FORWARD_QUERY_STRING_ATTR };
 
 
     /**
      * The string manager for this package.
      */
     protected static StringManager sm =
-        StringManager.getManager("org.apache.coyote.servlet");
+        StringManager.getManager("org.apache.tomcat.lite");
 
 
     // ----------------------------------------------------------- Constructors
@@ -89,8 +90,9 @@
      *
      * @param request The servlet request being wrapped
      */
-    public ServletRequestWrapperImpl(HttpServletRequest request, ServletContextImpl context,
-                                  boolean crossContext) {
+    public ServletRequestWrapperImpl(HttpServletRequest request, 
+                                     ServletContextImpl context,
+                                     boolean crossContext) {
 
         super(request);
         this.context = context;
@@ -300,7 +302,7 @@
 
         // Convert a request-relative path to a context-relative one
         String servletPath = 
-            (String) getAttribute(ServletRequestImpl.INCLUDE_SERVLET_PATH_ATTR);
+            (String) getAttribute(RequestDispatcherImpl.INCLUDE_SERVLET_PATH_ATTR);
         if (servletPath == null)
             servletPath = getServletPath();
 
@@ -563,7 +565,7 @@
                 return (false);
             if (context == null)
                 return (false);
-            WebappSessionManager manager = context.getManager();
+            SessionManagerServlet manager = context.getManager();
             if (manager == null)
                 return (false);
             HttpSessionImpl session = null;

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletResponseImpl.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletResponseImpl.java?rev=433260&r1=433259&r2=433260&view=diff
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletResponseImpl.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletResponseImpl.java Mon Aug 21 08:20:40 2006
@@ -36,6 +36,7 @@
 
 import org.apache.tomcat.lite.util.CharsetMapper;
 import org.apache.tomcat.lite.util.MessageWriter;
+import org.apache.tomcat.servlets.session.HttpSessionImpl;
 import org.apache.tomcat.util.buf.CharChunk;
 import org.apache.tomcat.util.buf.UEncoder;
 import org.apache.tomcat.util.http.FastHttpDateFormat;
@@ -88,7 +89,7 @@
      * The string manager for this package.
      */
     protected static StringManager sm =
-        StringManager.getManager("org.apache.coyote.servlet");
+        StringManager.getManager("org.apache.tomcat.lite");
 
 
     // ----------------------------------------------------- Instance Variables

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletResponseWrapperImpl.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletResponseWrapperImpl.java?rev=433260&r1=433259&r2=433260&view=diff
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletResponseWrapperImpl.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ServletResponseWrapperImpl.java Mon Aug 21 08:20:40 2006
@@ -41,26 +41,8 @@
  * keep these two classes in synchronization when making changes!
  *
  * @author Craig R. McClanahan
- * @version $Revision: 303387 $ $Date: 2004-10-15 09:09:27 -0700 (Fri, 15 Oct 2004) $
  */
-
-class ServletResponseWrapperImpl extends HttpServletResponseWrapper {
-
-
-    // ----------------------------------------------------------- Constructors
-
-
-    /**
-     * Construct a new wrapped response around the specified servlet response.
-     *
-     * @param response The servlet response being wrapped
-     */
-    public ServletResponseWrapperImpl(HttpServletResponse response) {
-
-        this(response, false);
-
-    }
-
+public class ServletResponseWrapperImpl extends HttpServletResponseWrapper {
 
     /**
      * Construct a new wrapped response around the specified servlet response.
@@ -71,30 +53,16 @@
      */
     public ServletResponseWrapperImpl(HttpServletResponse response,
                                    boolean included) {
-
         super(response);
-        setIncluded(included);
-
+        this.included = included;
     }
 
-
-    // ----------------------------------------------------- Instance Variables
-
-
     /**
      * Is this wrapped response the subject of an <code>include()</code>
      * call?
      */
     protected boolean included = false;
 
-
-    /**
-     * Descriptive information about this implementation.
-     */
-    protected static final String info =
-        "org.apache.catalina.core.ApplicationHttpResponse/1.0";
-
-
     /**
      * The string manager for this package.
      */
@@ -112,11 +80,9 @@
      *  been committed
      */
     public void reset() {
-
         // If already committed, the wrapped response will throw ISE
         if (!included || getResponse().isCommitted())
             getResponse().reset();
-
     }
 
 
@@ -207,10 +173,8 @@
      * @param value The new header value
      */
     public void addHeader(String name, String value) {
-
         if (!included)
             ((HttpServletResponse) getResponse()).addHeader(name, value);
-
     }
 
 
@@ -221,10 +185,8 @@
      * @param value The new header value
      */
     public void addIntHeader(String name, int value) {
-
         if (!included)
             ((HttpServletResponse) getResponse()).addIntHeader(name, value);
-
     }
 
 
@@ -236,10 +198,8 @@
      * @exception IOException if an input/output error occurs
      */
     public void sendError(int sc) throws IOException {
-
         if (!included)
             ((HttpServletResponse) getResponse()).sendError(sc);
-
     }
 
 
@@ -252,10 +212,8 @@
      * @exception IOException if an input/output error occurs
      */
     public void sendError(int sc, String msg) throws IOException {
-
         if (!included)
             ((HttpServletResponse) getResponse()).sendError(sc, msg);
-
     }
 
 
@@ -267,10 +225,8 @@
      * @exception IOException if an input/output error occurs
      */
     public void sendRedirect(String location) throws IOException {
-
         if (!included)
             ((HttpServletResponse) getResponse()).sendRedirect(location);
-
     }
 
 
@@ -281,10 +237,8 @@
      * @param value The new header value
      */
     public void setDateHeader(String name, long value) {
-
         if (!included)
             ((HttpServletResponse) getResponse()).setDateHeader(name, value);
-
     }
 
 
@@ -295,10 +249,8 @@
      * @param value The new header value
      */
     public void setHeader(String name, String value) {
-
         if (!included)
             ((HttpServletResponse) getResponse()).setHeader(name, value);
-
     }
 
 
@@ -309,10 +261,8 @@
      * @param value The new header value
      */
     public void setIntHeader(String name, int value) {
-
         if (!included)
             ((HttpServletResponse) getResponse()).setIntHeader(name, value);
-
     }
 
 
@@ -322,10 +272,8 @@
      * @param sc The new status code
      */
     public void setStatus(int sc) {
-
         if (!included)
             ((HttpServletResponse) getResponse()).setStatus(sc);
-
     }
 
 
@@ -336,57 +284,12 @@
      * @param msg The new message
      */
     public void setStatus(int sc, String msg) {
-
         if (!included)
             ((HttpServletResponse) getResponse()).setStatus(sc, msg);
-
-    }
-
-
-    // -------------------------------------------------------- Package Methods
-
-
-    /**
-     * Return descriptive information about this implementation.
-     */
-    public String getInfo() {
-
-        return (info);
-
     }
 
-
-    /**
-     * Return the included flag for this response.
-     */
-    boolean isIncluded() {
-
+    public boolean isIncluded() {
         return (this.included);
-
-    }
-
-
-    /**
-     * Set the included flag for this response.
-     *
-     * @param included The new included flag
-     */
-    void setIncluded(boolean included) {
-
-        this.included = included;
-
-    }
-
-
-    /**
-     * Set the response that we are wrapping.
-     *
-     * @param response The new wrapped response
-     */
-    void setResponse(HttpServletResponse response) {
-
-        super.setResponse(response);
-
     }
 
 

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java?rev=433260&view=auto
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java Mon Aug 21 08:20:40 2006
@@ -0,0 +1,354 @@
+/*
+ */
+package org.apache.tomcat.lite;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.Servlet;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+
+import org.apache.coyote.Request;
+import org.apache.coyote.Response;
+import org.apache.tomcat.lite.ctxmap.WebappContextMapper;
+import org.apache.tomcat.lite.util.MappingData;
+import org.apache.tomcat.lite.webmap.WebappFilterMapper;
+import org.apache.tomcat.lite.webmap.WebappServletMapper;
+import org.apache.tomcat.servlets.config.ServletData;
+import org.apache.tomcat.servlets.config.WebAppData;
+
+/**
+ * Frontend for a minimal servlet impl for Tomcat-Lite.
+ * 
+ * Almost all 'Servlet Container' functionality is implemented using Servlets,
+ * Filters, Listeners. Most of them are general-purpose, not specific and 
+ * not dependent on Tomcat-Lite. It is possible to replace any of them
+ * with application-specific ones, or to use some of the general ones on other 
+ * containers. 
+ * 
+ * There are 2 special webapps:
+ *  - __x_engine - defines the context mapper ( host + context path -> context),
+ *     defaults to be used in webapps ( default servlet, session management, 
+ *     etc ).
+ *     
+ *  - __x_deploy - optional webapp. If it is missing - a tomcatLite.ser file 
+ *     is required, containing all the config info, including processed web.xml
+ *     files. No new apps can be deployed, reload is not allowed. If present -
+ *     it'll provide the above mentioned features.
+ *     
+ * In addition:
+ *  - any context starting with __x_ will be loaded first
+ *  - context listeners for such apps will receive notifications for all 
+ *    contexts 
+ *  - in particular, __x_protocol_* webapp should contain the connectors. 
+ *  
+ *  For each 'module' ( connector, session manager, etc), the implementation
+ *  will be a filter or servlet, defined in __x_engine, with regular init
+ *  parameters in web.xml used to set up. Each webapp can override them
+ *  by defining a servlet with the same name ( names start with __x_ as well ).
+ *               
+ *
+ * This is based on catalina classes, with non-essential features removed. It is
+ * possible to add back some of the flexibility using callbacks/hooks - but this
+ * package should be a sufficient implementation for a working servlet
+ * container, with no extra features ( just hooks ).
+ * 
+ * @author Costin Manolache
+ */
+public class TomcatLite {
+    private static TomcatLite facade = new TomcatLite();
+
+    public static class EngineData implements Serializable {
+        // Informations about hosts - aliases, etc
+        public ArrayList<HostData> hosts = new ArrayList();
+        
+        // informations about contexts.
+        public ArrayList<ContextConfigData> contexts = new ArrayList();
+    }
+    
+    public static class HostData implements Serializable {
+        /** Must be lowercase */
+        public String hostName;
+        public ArrayList<String> aliases = new ArrayList();
+    }
+    
+    /** Data about webapps configured in the system
+     */
+    public static class ContextConfigData implements Serializable {
+        public ContextConfigData() {};
+        public ContextConfigData(String basePath, String path) {
+            this.basePath = basePath;
+            this.path = path;
+        }
+        public String hostName; // must be a canonical name
+        public String basePath; // dir - canonical or absolute
+        String path; // path where it is mapped. ( for multiple - use mapper,
+          // it is not allowed by spec )
+        
+        public WebAppData webXml;
+    }
+
+    EngineData data = new EngineData();
+    
+    WebappContextMapper hostMapper = new WebappContextMapper();
+    
+    // all contexts - hostMapper knows about hostnames and how they are mapped.
+    private ArrayList<ServletContextImpl> contexts = new ArrayList();
+
+    private EngineData engineData;
+
+    private TomcatLite() {
+    }
+
+    public static TomcatLite getServletImpl() {
+        return facade;
+    }
+
+    // --------------- start/stop ---------------
+
+    public void start() throws IOException {
+        long t0 = System.currentTimeMillis();
+
+        // start all contexts
+        // init all contexts
+        for(ServletContextImpl ctx: contexts) {
+            try {
+                ctx.init();
+                
+            } catch (Throwable e) {
+                e.printStackTrace();
+            }
+        }
+        saveEngineData(engineData);
+        long t1 = System.currentTimeMillis();
+        System.err.println("Engine.start() " + (t1-t0));
+    }
+
+    public void stop() {
+        // start all contexts
+        // init all contexts
+        for(ServletContextImpl ctx: contexts) {
+            try {
+                ctx.destroy();
+            } catch (Throwable e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    // -------------- Context add/remove --------------
+
+    /**
+     * 
+     * @param hostname - ""
+     *            if default host, or string to be matched with Host header
+     * @param path -
+     *            context path, "/" for root, "/examples", etc
+     * @return a servlet context
+     * @throws ServletException
+     */
+    public ServletContext addServletContext(String hostname, String basePath,
+                                            String path)
+        throws ServletException
+    {
+        ServletContextImpl ctx = new ServletContextImpl();
+        ctx.setContextPath(path);
+        ctx.setBasePath(basePath);
+
+        contexts.add(ctx);
+        // TODO: read web.xml or equivalent
+
+        // TODO: defaults
+        // 
+        hostMapper.addContext(hostname, ctx,
+                              new String[] { "index.html" },
+                              new File(basePath));
+
+
+        return ctx;
+    }
+    
+    public WebappContextMapper getContextMapper() {
+        return hostMapper;
+    }
+
+    public void removeServletContext(ServletContext sctx)
+        throws ServletException
+    {
+        ServletContextImpl ctx = (ServletContextImpl) sctx;
+        // TODO: destroy all servlets and filters
+        // TODO: clean up any other reference to the context or its loader
+        
+        hostMapper.removeContext(ctx);
+        notifyRemove(ctx);
+    }
+    
+    
+    public void service(ServletRequestImpl req, ServletResponseImpl res) throws Exception, IOException {
+        // parse the session id from URI
+        req.parseSessionId();
+        
+        try {
+            req.decodeRequest();
+        } catch(IOException ioe) {
+            res.setStatus(400);
+            return;
+        }
+        
+        MappingData mapRes = req.getMappingData();
+        try {
+            hostMapper.mapContext(req);
+            
+            ServletContextImpl ctx = (ServletContextImpl)mapRes.context;
+            if( ctx == null ) {
+                // TODO: 404
+                res.setStatus(404);
+                return;
+            }
+            req.setContext(ctx);
+
+            // bind class loader 
+            Thread.currentThread().setContextClassLoader(ctx.getClassLoader());
+
+            WebappServletMapper mapper = ctx.getMapper();
+            mapper.map(req.getDecodedRequestURIMB(), mapRes);
+
+            req.parseSessionCookiesId();
+
+            ServletConfigImpl h=(ServletConfigImpl)mapRes.wrapper;
+            if (h != null) {
+                serviceServlet(req, res, h, mapRes );
+            }
+        } finally {
+            if(mapRes != null ) 
+                mapRes.recycle();
+        }
+    }
+    
+    /** Coyote / mapper adapter. Result of the mapper.
+     *  
+     *  This replaces the valve chain, the path is: 
+     *    1. coyote calls mapper -> result Adapter 
+     *    2. service is called. Additional filters are set on the wrapper. 
+     * @param mapRes 
+     */
+    public void serviceServlet(ServletRequestImpl request, 
+                               ServletResponseImpl response,
+                               ServletConfigImpl servletConfig, MappingData mapRes) 
+        throws IOException {
+        
+        try {
+            Servlet servlet = servletConfig.allocate();
+            WebappFilterMapper filterMap = servletConfig.getParent().getFilterMapper();
+            FilterChainImpl chain = 
+                filterMap.createFilterChain(request, servletConfig, servlet);
+            
+            if (chain == null) {
+                servlet.service(request, response);
+            } else {
+                chain.doFilter(request, response);
+            }
+            
+            response.finishResponse();
+        } catch (IOException e) {
+            ;
+        } catch (Throwable t) {
+            t.printStackTrace();
+        } finally {
+            // Recycle the wrapper request and response
+            request.recycle();
+            response.recycle();
+        }
+    }
+ 
+    // ------------ Notifications for JMX ----------------
+
+    void notifyAdd(Object o) {
+    }
+
+    void notifyRemove(Object o) {
+    }
+
+    public void init() throws ServletException, IOException {
+        long t0 = System.currentTimeMillis();
+        File initFile = new File("tomcatLite.ser");
+        if (initFile.exists()) {
+            try {
+                ObjectInputStream ois = 
+                    new ObjectInputStream(new FileInputStream(initFile));
+                engineData = (EngineData)ois.readObject();
+            } catch(IOException ex) {
+                engineData = null;
+            } catch (ClassNotFoundException e) {
+                engineData = null;
+            }
+        }
+        if (engineData == null) {
+            // Ask the deploy app to initialize
+            ServletContextImpl deployCtx = 
+                (ServletContextImpl)addServletContext("localhost", 
+                                                      "webapps/__x_deploy", 
+                                                      "/__x_deploy");
+            ServletConfigImpl initSC = new ServletConfigImpl(deployCtx,
+                new ServletData("init", 
+                "org.apache.tomcat.servlets.deploy.InitServlet"));
+            deployCtx.addServletConfig(initSC);
+            deployCtx.init();
+            RequestDispatcher rd = deployCtx.getNamedDispatcher("init");
+            Request creq = new Request();
+            ServletRequestImpl req = new ServletRequestImpl();
+            req.setContextPath("/");
+            req.setContext(deployCtx);
+            req.setCoyoteRequest(creq);
+            Response cres = new Response();
+            ServletResponseImpl res = new ServletResponseImpl();
+            res.setRequest(req);
+            res.setCoyoteResponse(cres);
+            rd.forward(req, res);
+            
+            // end result - a context attribute must be set 
+            engineData = (EngineData)req.getAttribute("engineData");
+        }
+        
+        // Add the servlets
+        for (ContextConfigData ctxD: engineData.contexts) {
+            System.err.println("Loading context: " + ctxD.path + " " + ctxD.basePath);
+            ServletContextImpl ctx = 
+                (ServletContextImpl)addServletContext(null, 
+                                                      ctxD.basePath, 
+                                                      ctxD.path);
+            ctx.setContextConfigData(ctxD);
+            if (ctxD.webXml != null) {
+                ctx.processWebAppData(ctxD.webXml);
+            }
+        }
+        long t1 = System.currentTimeMillis();
+        System.err.println("Engine.init() " + (t1-t0));
+    }
+    
+    public void saveEngineData(EngineData ed)
+        throws FileNotFoundException, IOException
+    {
+        FileOutputStream fos = new FileOutputStream("tomcatLite.ser");
+        ObjectOutputStream oos = new ObjectOutputStream(fos);
+        oos.writeObject(ed);
+        oos.close();
+    }
+
+    
+    public static void main(String args[]) 
+            throws ServletException, IOException {
+        TomcatLite facade = TomcatLite.getServletImpl();
+        facade.init();
+        facade.start();
+    }
+}

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ctxmap/WebappContextMapper.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ctxmap/WebappContextMapper.java?rev=433260&view=auto
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ctxmap/WebappContextMapper.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/ctxmap/WebappContextMapper.java Mon Aug 21 08:20:40 2006
@@ -0,0 +1,319 @@
+package org.apache.tomcat.lite.ctxmap;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.apache.tomcat.lite.ServletContextImpl;
+import org.apache.tomcat.lite.ServletRequestImpl;
+import org.apache.tomcat.lite.TomcatLite.HostData;
+import org.apache.tomcat.lite.util.MappingData;
+import org.apache.tomcat.lite.webmap.WebappServletMapper;
+import org.apache.tomcat.lite.webmap.WebappServletMapper.ContextMapElement;
+import org.apache.tomcat.util.buf.CharChunk;
+import org.apache.tomcat.util.buf.MessageBytes;
+
+/** 
+ * This handles host and context mapping - the data structures are stored
+ * in this class. 
+ * 
+ * All context-specific mapping is done in the Mapper class, one per
+ * context. Mapper should also handle filters and authentication.
+ * 
+ * You can extend and override the mapper in MapperAdapter.
+ */
+public class WebappContextMapper implements Filter {
+    
+    /** Data we store for each host 
+     */
+    static class HostMappingInfo
+    {
+       public HostData hostData;
+       // <String path, ServletContextImp>
+       private HashMap children = new HashMap();
+       // Used by the mapper
+       ContextMapElement[] contexts = new ContextMapElement[0];
+       int nesting = 0;
+       
+       public String toString() {
+           StringBuffer sb = new StringBuffer();
+           
+           sb.append("HostMappingInfo { nesting: " + nesting + 
+           "\n hostName" + hostData.hostName);
+           for( int i=0; i < contexts.length; i++) {
+               sb.append(contexts[i].toString());
+           }
+           sb.append("\n}");
+           return sb.toString();
+       }
+
+   }
+
+    /** String lowercase(hostname) -> Host object
+     *  All aliases are included.
+     */
+    Map<String, HostMappingInfo> hostMap = new HashMap();
+    
+    // could it be multiple hosts ?
+    HashMap<ServletContextImpl, HostMappingInfo> contextsParents = new HashMap();
+    
+    // If no host or alias matches
+    HostMappingInfo defaultHost = new HostMappingInfo();
+    
+    public WebappContextMapper() {
+        defaultHost.hostData= new HostData();
+        defaultHost.hostData.hostName = "";
+        hostMap.put("", defaultHost);
+    }
+    
+    /**
+     * Add a new host to the mapper.
+     *
+     * @param name Virtual host name
+     * @param host Host object
+     */
+    public void addHost(String name, String[] aliases) {
+        HostMappingInfo host = new HostMappingInfo();
+        hostMap.put(name.toLowerCase(), host);
+        for (int i = 0; i < aliases.length; i++) {
+            hostMap.put(aliases[i].toLowerCase(), host);
+        }
+    }
+    
+    /**
+     * Remove a host from the mapper.
+     *
+     * @param name Virtual host name
+     */
+    public void removeHost(String name) {
+        HostMappingInfo host = findHost(name);
+        if (host == null) {
+            return;
+        }
+        Iterator hostIt = hostMap.entrySet().iterator();
+        while( hostIt.hasNext()) {
+            Map.Entry entry = (Map.Entry)hostIt.next();
+            if(entry.getValue() == host) {
+                hostIt.remove();
+            }
+        }
+    }
+
+    /**
+     * Add a new Context to an existing Host.
+     *
+     * @param hostName Virtual host name this context belongs to
+     * @param contextPath Context path
+     * @param context Context object
+     * @param welcomeResources Welcome files defined for this context
+     * @param resources Static resources of the context
+     */
+    public void addContext(String hostName, ServletContextImpl context,
+         String[] welcomeResources, File resources) 
+        throws ServletException
+    {
+        HostMappingInfo host = findHost(hostName);
+        
+        String path = context.getContextPath();
+        host.children.put(path, context);
+        contextsParents.put(context, host);
+
+        int slashCount = WebappServletMapper.slashCount(path);
+        if (slashCount > host.nesting) {
+            host.nesting = slashCount;
+        }
+        ContextMapElement[] contexts = host.contexts;
+        ContextMapElement[] newContexts = new ContextMapElement[contexts.length + 1];
+        ContextMapElement newContext = context.getMapper().contextMapElement;
+        newContext.name = path;
+        newContext.object = context;
+        newContext.welcomeResources = welcomeResources;
+        newContext.resources = resources;
+        if (WebappServletMapper.insertMap(contexts, newContexts, newContext)) {
+            host.contexts = newContexts;
+        }
+        
+    }
+
+
+    /**
+     * Remove a context from an existing host.
+     *
+     * @param hostName Virtual host name this context belongs to
+     * @param path Context path
+     */
+    public void removeContext(String hostName, String path) 
+            throws ServletException {
+        HostMappingInfo host = findHost(hostName);
+        if (host == null) throw new ServletException("Host not found");
+        if (host.hostData.hostName.equals(hostName)) {
+            synchronized (host) {
+                ContextMapElement[] contexts = host.contexts;
+                if( contexts.length == 0 ){
+                    return;
+                }
+                ContextMapElement[] newContexts = new ContextMapElement[contexts.length - 1];
+                if (WebappServletMapper.removeMap(contexts, newContexts, path)) {
+                    host.contexts = newContexts;
+                    // Recalculate nesting
+                    host.nesting = 0;
+                    for (int i = 0; i < newContexts.length; i++) {
+                        int slashCount = WebappServletMapper.slashCount(newContexts[i].name);
+                        if (slashCount > host.nesting) {
+                            host.nesting = slashCount;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+
+    // -------------------------------------------------------- Private Methods
+
+    /** Find a the host. 
+     *  Override for corner cases ( wildcards, huge number of hosts, 
+     *  special patterns, dynamic behavior ).
+     *  
+     */
+    public HostMappingInfo findHost(String hostName) {
+        if (hostName == null || "".equals(hostName)) return defaultHost;
+        HostMappingInfo host = null;
+        if(hostMap.size() > 0 ) {
+            // don't bother if we only have default host
+            host = (HostMappingInfo)hostMap.get(hostName.toLowerCase());
+        }
+        if (host == null) host = defaultHost;
+        return host;
+    }
+    
+    /**
+     * Map the specified URI.
+     */
+    public void mapContext(ServletRequestImpl req)
+            throws Exception {
+        String host = req.getHeader("Host");
+        MessageBytes uriMB = req.getDecodedRequestURIMB();
+        MappingData mappingData = req.getMappingData(); 
+
+        if (host == null)  {
+            host = defaultHost.hostData.hostName;
+        }
+        uriMB.toChars();
+        CharChunk uri = uriMB.getCharChunk();
+        
+        uri.setLimit(-1);
+
+        // Virtual host mapping
+        if (mappingData.host == null) {
+            mappingData.host = findHost(host.toString());
+        }
+        if (mappingData.host == null) {
+            throw new ServletException("Host not found");
+        }
+
+        ContextMapElement[] contexts =  
+            ((HostMappingInfo)mappingData.host).contexts;
+        ContextMapElement context = null;
+        int nesting = ((HostMappingInfo)mappingData.host).nesting;
+
+        // Context mapping
+        if (mappingData.context == null) {
+            int pos = WebappServletMapper.find(contexts, uri);
+            if (pos == -1) {
+                mappingData.context = contexts[0].object;
+                mappingData.contextPath.setString(contexts[0].name);
+                return;
+            }
+
+            int lastSlash = -1;
+            int uriEnd = uri.getEnd();
+            int length = -1;
+            boolean found = false;
+            while (pos >= 0) {
+                if (uri.startsWith(contexts[pos].name)) {
+                    length = contexts[pos].name.length();
+                    if (uri.getLength() == length) {
+                        found = true;
+                        break;
+                    } else if (uri.startsWithIgnoreCase("/", length)) {
+                        found = true;
+                        break;
+                    }
+                }
+                if (lastSlash == -1) {
+                    lastSlash = WebappServletMapper.nthSlash(uri, nesting + 1);
+                } else {
+                    lastSlash = WebappServletMapper.lastSlash(uri);
+                }
+                uri.setEnd(lastSlash);
+                pos = WebappServletMapper.find(contexts, uri);
+            }
+            uri.setEnd(uriEnd);
+
+            if (!found) {
+                mappingData.context = contexts[0].object;
+                mappingData.contextPath.setString(contexts[0].name);
+            } else {
+                context = contexts[pos];
+                mappingData.context = context.object;
+                mappingData.contextPath.setString(context.name);
+            }
+        }
+    }
+
+    
+    public void init(FilterConfig filterConfig) throws ServletException {
+    }
+    
+    public void doFilter(ServletRequest request, 
+                         ServletResponse response, 
+                         FilterChain chain) 
+            throws IOException, ServletException {
+    }
+    
+    public void destroy() {
+    }
+    
+    public ServletContextImpl getContext(ServletContextImpl impl, String uri) {
+        HostMappingInfo host = contextsParents.get(impl);
+        if (host == null) host = defaultHost;
+        return getContext(host, uri);
+    }
+    
+    public ServletContextImpl getContext(HostMappingInfo host, String uri) {
+        ServletContextImpl child = null;
+        try {
+            
+            String mapuri = uri;
+            while (true) {
+                child = (ServletContextImpl) host.children.get(mapuri);
+                if (child != null)
+                    break;
+                int slash = mapuri.lastIndexOf('/');
+                if (slash < 0)
+                    break;
+                mapuri = mapuri.substring(0, slash);
+            }
+        } catch (Throwable t) {
+            return (null);
+        }
+        return child;
+    }
+
+    public void removeContext(ServletContextImpl ctx) {
+        // TODO Auto-generated method stub
+        
+    }
+
+
+}
\ No newline at end of file

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/http/CoyoteAdapter.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/http/CoyoteAdapter.java?rev=433260&view=auto
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/http/CoyoteAdapter.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/http/CoyoteAdapter.java Mon Aug 21 08:20:40 2006
@@ -0,0 +1,118 @@
+package org.apache.tomcat.lite.http;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+
+import org.apache.coyote.ActionCode;
+import org.apache.coyote.Adapter;
+import org.apache.coyote.Request;
+import org.apache.coyote.Response;
+import org.apache.tomcat.lite.TomcatLite;
+import org.apache.tomcat.lite.ServletRequestImpl;
+import org.apache.tomcat.lite.ServletResponseImpl;
+import org.apache.tomcat.lite.util.MessageWriter;
+import org.apache.tomcat.util.net.http11.Http11Protocol;
+
+/** Main adapter - top mapping and adaptation.
+ * 
+ * This handles host and context mapping - the data structures are stored
+ * in this class. 
+ * 
+ * All context-specific mapping is done in the Mapper class, one per
+ * context. Mapper should also handle filters and authentication.
+ */
+public class CoyoteAdapter extends HttpServlet implements Adapter {
+
+
+    protected Http11Protocol proto;
+
+    private TomcatLite facade;
+
+    public CoyoteAdapter() {
+        proto = new Http11Protocol();
+        proto.setAdapter(this);
+        facade = TomcatLite.getServletImpl();
+    }
+    
+    public void init() throws ServletException {
+        try {
+            proto.getEndpoint().setPort(8800);
+            proto.getEndpoint().setDaemon(false);        
+            proto.init();
+            proto.start();
+        } catch (Exception e) {
+            throw new ServletException(e);
+        }
+
+    }
+    
+    public void destroy() {
+        try {
+            proto.destroy();
+        } catch (Exception e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+    }
+    
+    /**
+     * Fine tunning
+     */
+    public Http11Protocol getProtocol() {
+        return proto;
+    }
+
+    /** 
+     */
+    public void setPort(int port) {
+        proto.getEndpoint().setPort(port);
+    }
+
+
+    public static final int ADAPTER_NOTES = 1;
+
+
+    public void service(Request cReq, final Response cRes)
+            throws Exception {
+        try {
+
+            ServletRequestImpl req = 
+                (ServletRequestImpl) cReq.getNote(ADAPTER_NOTES);
+            ServletResponseImpl res = 
+                (ServletResponseImpl) cRes.getNote(ADAPTER_NOTES);
+            if (req == null) {
+                // Create objects
+                req = new ServletRequestImpl();
+                req.setCoyoteRequest(cReq);
+                res = new ServletResponseImpl();
+                res.setRequest(req);
+                res.setCoyoteResponse(cRes);
+                // Link objects
+                req.setResponse(res);
+
+                // Set as notes
+                cReq.setNote(ADAPTER_NOTES, req);
+                cRes.setNote(ADAPTER_NOTES, res);
+            }
+
+            facade.service(req, res);
+            cReq.action( ActionCode.ACTION_POST_REQUEST , null);
+
+        } catch( Throwable t ) {
+            t.printStackTrace(System.out);
+        }
+
+        // Final processing
+        MessageWriter.getWriter(cReq, cRes, 0).flush();
+        cRes.finish();
+        cReq.recycle();
+        cRes.recycle();
+
+    }
+    
+   
+    public boolean event(Request req, Response res, boolean error) 
+            throws Exception {
+        return false;
+    }
+}
\ No newline at end of file

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/jmx/JmxListener.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/jmx/JmxListener.java?rev=433260&r1=433259&r2=433260&view=diff
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/jmx/JmxListener.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/jmx/JmxListener.java Mon Aug 21 08:20:40 2006
@@ -1,22 +1,28 @@
 package org.apache.tomcat.lite.jmx;
 
-import org.apache.tomcat.lite.ServletFacade.ManagedObjectListener;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
 
-public class JmxListener implements ManagedObjectListener {
+/**
+ *  - TODO: all attributes starting with _jmx_NAME will be automatically exposed to 
+ *   jmx
+ *   
+ *  - register the context with JMX ( the 'internal' context gets all 
+ *  notifications )
+ *  
+ *  
+ *  
+ * @author costin
+ */
+public class JmxListener implements ServletContextListener {
 
-    public void addManagedObject(Object o) {
-        String cls = o.getClass().getName();
-        if (cls.endsWith("ServletContextImpl")) {
-            
-        } else if (cls.endsWith("ServletConfigImpl")) {
-            
-        } else if (cls.endsWith("Host")) {
-            
-        }
-             
+    public void contextDestroyed(ServletContextEvent sce) {
+        // TODO Auto-generated method stub
+        
     }
 
-    public void removeManagedObject(Object o) {
+    public void contextInitialized(ServletContextEvent sce) {
+        // TODO Auto-generated method stub
         
     }
 

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/package.html
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/package.html?rev=433260&r1=433259&r2=433260&view=diff
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/package.html (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/package.html Mon Aug 21 08:20:40 2006
@@ -1,6 +1,73 @@
-<h2>Minimal version of tomcat</h2>
+<h2>Minimal, user-space version of tomcat</h2>
 
+<p>The goal of this project is to refactor tomcat code in a minimal core, 
+implementing HTTP/1.1 or other protocols, and a set of user-space 
+filters/listeners/servlets/utils that implement the higher level part of the 
+servlet API.</p>
+
+<p>By user space we mean regular servlets, with no direct dependnecy on any
+contaniner, and can be used indepdent of a servlet container, in regular
+webapplications. The goal is to give more power and flexibility to webapps, and 
+to fix the root cause of all the complexity we see in tomcat and servlet 
+containers - the need for features that can only be addressed in the container
+</p>
+
+<h3>Setting up the user-space components</h3>
+
+In Tomcat-Lite, the user space components are defined in web.xml of the 
+app, with simple defaults. The communication between container and user space
+is done by using attributes and by container calling the user space components.
+To extend tomcat-lite, you need to extend the base user-space filters/servltes,
+and configure your replacement. ( see example webapp ).
+
+In any other container, you can use the user-space components just like you 
+would use a third-party library and servlets. You set them up in web.xml, and 
+then use them using the public API each compoent defines. See next sections
+for details and examples.
+
+Each servlet's javadoc describes how to use it as an independent component, 
+in a 3rd party container. Tomcat-Lite uses the same APIs to hook the 
+servlet behind Servlet APIs. 
+
+You can have session manangement, authentication, mapping, etc implemented 
+as a library - with whatever behavior and customization you need. This can
+be used in webapps, using the APIs exposed by the library ( ex. 
+MySessionManager.getHttpSession(), or MyAuthorizationFilter.filter(req, res) ).
+Tomcat-Lite just happens to hook the library behind the Servlet API ( while 
+still allowing direct use ) - so ServletRequest.getSession() will call
+MySessionManager.getHttpSession().
+
+This also takes care of the configuration - MySessionManager can be a servlet,
+that is set up in normal web.xml and has it's own init params, and may even
+expose status info or do anything you can dream of - there is no restriction
+or servlet-container imposed rule.     
+
+
+<h3>Session management</h3>
+
+<p>The session manager is implemented as Servlet, with the 
+base class org.apache.tomcat.servlets.session.WebappSessionManager. The class
+will set itself as a context attribute: __SERVLET_IMPL__.SessionManager. 
+
+To use it from a webapp, use:
+
+<pre>
+ // Old code:
+ // req.getSession(newSession);
+  
+ WebappSessionManager sm = 
+     WebappSessionManager.getSessionManager(getServletContext());
+ HttpSession session = sm.getSession(req, res, newSession);
+<pre> 
+
+<h3>Authentication</h3>
+
+
+
+<h3>JMX and management</h3>
 
+<p>Need to make calls to a library, will use modeler - no direct dep on 
+jmx.</p>
 
 <h3>Changes  (compared with catalina classes)</h3>
 
@@ -28,6 +95,7 @@
 <h3>TODO</h3>
 
 <ul>
-<li>Thread for background tasks, including session expiry
+<li>Add back the thread for background tasks, including session expiry ( as a 
+generic utility library ) 
 </li><li>
 </li></ul>

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/util/CharsetMapper.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/util/CharsetMapper.java?rev=433260&r1=433259&r2=433260&view=diff
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/util/CharsetMapper.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/util/CharsetMapper.java Mon Aug 21 08:20:40 2006
@@ -45,7 +45,7 @@
      * Default properties resource name.
      */
     public static final String DEFAULT_RESOURCE =
-      "/org/apache/coyote/servlet/util/CharsetMapperDefault.properties";
+      "/org/apache/tomcat/lite/util/CharsetMapperDefault.properties";
 
 
     // ---------------------------------------------------------- Constructors

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/util/ParameterMap.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/util/ParameterMap.java?rev=433260&r1=433259&r2=433260&view=diff
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/util/ParameterMap.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/util/ParameterMap.java Mon Aug 21 08:20:40 2006
@@ -126,7 +126,7 @@
      * The string manager for this package.
      */
     private static final StringManager sm =
-        StringManager.getManager("org.apache.coyote.servlet.util");
+        StringManager.getManager("org.apache.tomcat.lite.util");
 
 
     // --------------------------------------------------------- Public Methods

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/webmap/WebappFilterMapper.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/webmap/WebappFilterMapper.java?rev=433260&view=auto
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/webmap/WebappFilterMapper.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/lite/webmap/WebappFilterMapper.java Mon Aug 21 08:20:40 2006
@@ -0,0 +1,534 @@
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.tomcat.lite.webmap;
+
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.ArrayList;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.tomcat.lite.FilterChainImpl;
+import org.apache.tomcat.lite.FilterConfigImpl;
+import org.apache.tomcat.lite.ServletConfigImpl;
+import org.apache.tomcat.lite.ServletContextImpl;
+import org.apache.tomcat.lite.ServletRequestImpl;
+import org.apache.tomcat.servlets.util.RequestUtil;
+
+/**
+ * First filter after the context and servlet are mapped. It will add 
+ * web.xml-defined filters. 
+ * 
+ * costin: This is another mapping - done in RequestDispatcher or initial 
+ * mapping.
+ * Also: StandardHostValve - sets attribute for error pages,
+ *   StandardWrapperValve - mapping per invocation
+ *
+ * @author Greg Murray
+ * @author Remy Maucherat
+ */
+public class WebappFilterMapper implements Filter {
+
+
+    // -------------------------------------------------------------- Constants
+
+
+    public static final int ERROR = 1;
+    public static final Integer ERROR_INTEGER = new Integer(ERROR);
+    public static final int FORWARD = 2;
+    public static final Integer FORWARD_INTEGER = new Integer(FORWARD);
+    public static final int INCLUDE = 4;
+    public static final Integer INCLUDE_INTEGER = new Integer(INCLUDE);
+    public static final int REQUEST = 8;
+    public static final Integer REQUEST_INTEGER = new Integer(REQUEST);
+
+    /**
+     * Request dispatcher state.
+     */
+    public static final String DISPATCHER_TYPE_ATTR = 
+        "org.apache.catalina.core.DISPATCHER_TYPE";
+
+    /**
+     * Request dispatcher path.
+     */
+    public static final String DISPATCHER_REQUEST_PATH_ATTR = 
+        "org.apache.catalina.core.DISPATCHER_REQUEST_PATH";
+
+
+    // ----------------------------------------------------------- Constructors
+    ServletContextImpl servletContext;
+
+    public WebappFilterMapper() {
+    }
+
+    public WebappFilterMapper(ServletContextImpl impl) {
+        servletContext = impl;
+    }
+
+    public void setServletContext(ServletContextImpl sc) {
+        servletContext = sc;
+    }
+
+    // --------------------------------------------------------- Public Methods
+
+    ArrayList filterMaps = new ArrayList();
+    
+    public void addMapping(String filterName, 
+                           String url, 
+                           String servletName, 
+                           String type[]) {
+        FilterMap map = new FilterMap();
+        map.setURLPattern(url);
+        map.setFilterName(filterName);
+        map.setServletName(servletName);
+        filterMaps.add(map);
+    }
+
+    /**
+     * Construct and return a FilterChain implementation that will wrap the
+     * execution of the specified servlet instance.  If we should not execute
+     * a filter chain at all, return <code>null</code>.
+     *
+     * @param request The servlet request we are processing
+     * @param servlet The servlet instance to be wrapped
+     */
+    public FilterChainImpl createFilterChain(ServletRequest request, 
+                                             ServletConfigImpl wrapper, 
+                                             Servlet servlet) {
+
+        // If there is no servlet to execute, return null
+        if (servlet == null)
+            return (null);
+
+        // get the dispatcher type
+        int dispatcher = -1; 
+        if (request.getAttribute(DISPATCHER_TYPE_ATTR) != null) {
+            Integer dispatcherInt = 
+                (Integer) request.getAttribute(DISPATCHER_TYPE_ATTR);
+            dispatcher = dispatcherInt.intValue();
+        }
+        String requestPath = null;
+        Object attribute = request.getAttribute(DISPATCHER_REQUEST_PATH_ATTR);
+        
+        if (attribute != null){
+            requestPath = attribute.toString();
+        }
+        
+        HttpServletRequest hreq = null;
+        if (request instanceof HttpServletRequest) 
+            hreq = (HttpServletRequest)request;
+
+        // Create and initialize a filter chain object
+        FilterChainImpl filterChain = null;
+        if ((request instanceof ServletRequestImpl)) {
+            ServletRequestImpl req = (ServletRequestImpl) request;
+            filterChain = (FilterChainImpl) req.getFilterChain();
+            filterChain.release();
+        } else {
+            // Security: Do not recycle
+            filterChain = new FilterChainImpl();
+        }
+
+        filterChain.setServlet(wrapper, servlet);
+
+        // If there are no filter mappings, we are done
+        if ((filterMaps.size() == 0))
+            return (filterChain);
+
+        // Acquire the information we will need to match filter mappings
+        String servletName = wrapper.getServletName();
+
+        int n = 0;
+
+        // TODO(costin): optimize: separate in 2 lists, one for url-mapped, one for
+        // servlet-name. Maybe even separate list for dispatcher and 
+        // non-dispatcher
+        
+        // TODO(costin): optimize: set the FilterConfig in the FilterMap, to 
+        // avoid second hash lookup
+        
+        // Add the relevant path-mapped filters to this filter chain
+        for (int i = 0; i < filterMaps.size(); i++) {
+            FilterMap filterMap = (FilterMap)filterMaps.get(i);
+            if (!matchDispatcher(filterMap ,dispatcher)) {
+                continue;
+            }
+            if (!matchFiltersURL(filterMap, requestPath))
+                continue;
+            FilterConfigImpl filterConfig = 
+                servletContext.getFilter(filterMap.getFilterName());
+            if (filterConfig == null) {
+                // FIXME - log configuration problem
+                continue;
+            }
+            filterChain.addFilter(filterConfig);
+            n++;
+        }
+
+        // Add filters that match on servlet name second
+        for (int i = 0; i < filterMaps.size(); i++) {
+            FilterMap filterMap = (FilterMap)filterMaps.get(i);
+            if (!matchDispatcher(filterMap ,dispatcher)) {
+                continue;
+            }
+            if (!matchFiltersServlet(filterMap, servletName))
+                continue;
+            FilterConfigImpl filterConfig = 
+                servletContext.getFilter(filterMap.getFilterName());
+            if (filterConfig == null) {
+                ;       // FIXME - log configuration problem
+                continue;
+            }
+            filterChain.addFilter(filterConfig);
+            n++;
+        }
+
+        // Return the completed filter chain
+        return (filterChain);
+
+    }
+
+
+    // -------------------------------------------------------- Private Methods
+
+
+    /**
+     * Return <code>true</code> if the context-relative request path
+     * matches the requirements of the specified filter mapping;
+     * otherwise, return <code>null</code>.
+     *
+     * @param filterMap Filter mapping being checked
+     * @param requestPath Context-relative request path of this request
+     */
+    private boolean matchFiltersURL(FilterMap filterMap, String requestPath) {
+
+        if (requestPath == null)
+            return (false);
+
+        // Match on context relative request path
+        String testPath = filterMap.getURLPattern();
+        if (testPath == null)
+            return (false);
+
+        // Case 1 - Exact Match
+        if (testPath.equals(requestPath))
+            return (true);
+
+        // Case 2 - Path Match ("/.../*")
+        if (testPath.equals("/*"))
+            return (true);
+        if (testPath.endsWith("/*")) {
+            if (testPath.regionMatches(0, requestPath, 0, 
+                                       testPath.length() - 2)) {
+                if (requestPath.length() == (testPath.length() - 2)) {
+                    return (true);
+                } else if ('/' == requestPath.charAt(testPath.length() - 2)) {
+                    return (true);
+                }
+            }
+            return (false);
+        }
+
+        // Case 3 - Extension Match
+        if (testPath.startsWith("*.")) {
+            int slash = requestPath.lastIndexOf('/');
+            int period = requestPath.lastIndexOf('.');
+            if ((slash >= 0) && (period > slash) 
+                && (period != requestPath.length() - 1)
+                && ((requestPath.length() - period) 
+                    == (testPath.length() - 1))) {
+                return (testPath.regionMatches(2, requestPath, period + 1,
+                                               testPath.length() - 2));
+            }
+        }
+
+        // Case 4 - "Default" Match
+        return (false); // NOTE - Not relevant for selecting filters
+
+    }
+
+
+    /**
+     * Return <code>true</code> if the specified servlet name matches
+     * the requirements of the specified filter mapping; otherwise
+     * return <code>false</code>.
+     *
+     * @param filterMap Filter mapping being checked
+     * @param servletName Servlet name being checked
+     */
+    private boolean matchFiltersServlet(FilterMap filterMap, 
+                                        String servletName) {
+
+        if (servletName == null) {
+            return (false);
+        } else {
+            if (servletName.equals(filterMap.getServletName())) {
+                return (true);
+            } else {
+                return false;
+            }
+        }
+
+    }
+
+
+    /**
+     * Convienience method which returns true if  the dispatcher type
+     * matches the dispatcher types specified in the FilterMap
+     */
+    private boolean matchDispatcher(FilterMap filterMap, int dispatcher) {
+        switch (dispatcher) {
+            case FORWARD : {
+                if (filterMap.getDispatcherMapping() == FilterMap.FORWARD ||
+                    filterMap.getDispatcherMapping() == FilterMap.FORWARD_ERROR ||
+                    filterMap.getDispatcherMapping() == FilterMap.INCLUDE_FORWARD ||
+                    filterMap.getDispatcherMapping() == FilterMap.INCLUDE_ERROR_FORWARD ||
+                    filterMap.getDispatcherMapping() == FilterMap.REQUEST_FORWARD ||
+                    filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD ||
+                    filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD_INCLUDE ||
+                    filterMap.getDispatcherMapping() == FilterMap.REQUEST_FORWARD_INCLUDE) {
+                        return true;
+                }
+                break;
+            }
+            case INCLUDE : {
+                if (filterMap.getDispatcherMapping() == FilterMap.INCLUDE ||
+                    filterMap.getDispatcherMapping() == FilterMap.INCLUDE_ERROR ||
+                    filterMap.getDispatcherMapping() == FilterMap.INCLUDE_FORWARD ||
+                    filterMap.getDispatcherMapping() == FilterMap.INCLUDE_ERROR_FORWARD ||
+                    filterMap.getDispatcherMapping() == FilterMap.REQUEST_INCLUDE ||
+                    filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_INCLUDE ||
+                    filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD_INCLUDE ||
+                    filterMap.getDispatcherMapping() == FilterMap.REQUEST_FORWARD_INCLUDE) {
+                        return true;
+                }
+                break;
+            }
+            case REQUEST : {
+                if (filterMap.getDispatcherMapping() == FilterMap.REQUEST ||
+                    filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR ||
+                    filterMap.getDispatcherMapping() == FilterMap.REQUEST_INCLUDE ||
+                    filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_INCLUDE ||
+                    filterMap.getDispatcherMapping() == FilterMap.REQUEST_FORWARD ||
+                    filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD ||
+                    filterMap.getDispatcherMapping() == FilterMap.REQUEST_FORWARD_INCLUDE ||
+                    filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD_INCLUDE) {
+                        return true;
+                }
+                break;
+            }
+            case ERROR : {
+                if (filterMap.getDispatcherMapping() == FilterMap.ERROR ||
+                    filterMap.getDispatcherMapping() == FilterMap.FORWARD_ERROR || 
+                    filterMap.getDispatcherMapping() == FilterMap.INCLUDE_ERROR || 
+                    filterMap.getDispatcherMapping() == FilterMap.INCLUDE_ERROR_FORWARD || 
+                    filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR ||
+                    filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD ||
+                    filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_FORWARD_INCLUDE ||
+                    filterMap.getDispatcherMapping() == FilterMap.REQUEST_ERROR_INCLUDE) {
+                        return true;
+                }
+                break;
+            }
+        }
+        return false;
+    }
+
+
+    // -------------------- Map elements -----------------------
+    
+    public static class FilterMap implements Serializable {
+
+
+        // ------------------------------------------------------------- Properties
+
+
+        /**
+         * The name of this filter to be executed when this mapping matches
+         * a particular request.
+         */
+        
+        public static final int ERROR = 1;
+        public static final int FORWARD = 2;
+        public static final int FORWARD_ERROR =3;  
+        public static final int INCLUDE = 4;
+        public static final int INCLUDE_ERROR  = 5;
+        public static final int INCLUDE_ERROR_FORWARD  =6;
+        public static final int INCLUDE_FORWARD  = 7;
+        public static final int REQUEST = 8;
+        public static final int REQUEST_ERROR = 9;
+        public static final int REQUEST_ERROR_FORWARD = 10;
+        public static final int REQUEST_ERROR_FORWARD_INCLUDE = 11;
+        public static final int REQUEST_ERROR_INCLUDE = 12;
+        public static final int REQUEST_FORWARD = 13;
+        public static final int REQUEST_INCLUDE = 14;
+        public static final int REQUEST_FORWARD_INCLUDE= 15;
+        
+        // represents nothing having been set. This will be seen 
+        // as equal to a REQUEST
+        private static final int NOT_SET = -1;
+        
+        private int dispatcherMapping=NOT_SET;
+        
+        private String filterName = null;    
+
+        /**
+         * The URL pattern this mapping matches.
+         */
+        private String urlPattern = null;
+
+        /**
+         * The servlet name this mapping matches.
+         */
+        private String servletName = null;
+
+
+
+        public String getFilterName() {
+            return (this.filterName);
+        }
+
+        public void setFilterName(String filterName) {
+            this.filterName = filterName;
+        }
+
+
+        public String getServletName() {
+            return (this.servletName);
+        }
+
+        public void setServletName(String servletName) {
+            this.servletName = servletName;
+        }
+
+
+        public String getURLPattern() {
+            return (this.urlPattern);
+        }
+
+        public void setURLPattern(String urlPattern) {
+            this.urlPattern = RequestUtil.URLDecode(urlPattern);
+        }
+        
+        /**
+         *
+         * This method will be used to set the current state of the FilterMap
+         * representing the state of when filters should be applied:
+         *
+         *        ERROR
+         *        FORWARD
+         *        FORWARD_ERROR
+         *        INCLUDE
+         *        INCLUDE_ERROR
+         *        INCLUDE_ERROR_FORWARD
+         *        REQUEST
+         *        REQUEST_ERROR
+         *        REQUEST_ERROR_INCLUDE
+         *        REQUEST_ERROR_FORWARD_INCLUDE
+         *        REQUEST_INCLUDE
+         *        REQUEST_FORWARD,
+         *        REQUEST_FORWARD_INCLUDE
+         *
+         */
+        public void setDispatcher(String dispatcherString) {
+            String dispatcher = dispatcherString.toUpperCase();
+            
+            if (dispatcher.equals("FORWARD")) {
+
+                // apply FORWARD to the global dispatcherMapping.
+                switch (dispatcherMapping) {
+                    case NOT_SET  :  dispatcherMapping = FORWARD; break;
+                    case ERROR : dispatcherMapping = FORWARD_ERROR; break;
+                    case INCLUDE  :  dispatcherMapping = INCLUDE_FORWARD; break;
+                    case INCLUDE_ERROR  :  dispatcherMapping = INCLUDE_ERROR_FORWARD; break;
+                    case REQUEST : dispatcherMapping = REQUEST_FORWARD; break;
+                    case REQUEST_ERROR : dispatcherMapping = REQUEST_ERROR_FORWARD; break;
+                    case REQUEST_ERROR_INCLUDE : dispatcherMapping = REQUEST_ERROR_FORWARD_INCLUDE; break;
+                    case REQUEST_INCLUDE : dispatcherMapping = REQUEST_FORWARD_INCLUDE; break;
+                }
+            } else if (dispatcher.equals("INCLUDE")) {
+                // apply INCLUDE to the global dispatcherMapping.
+                switch (dispatcherMapping) {
+                    case NOT_SET  :  dispatcherMapping = INCLUDE; break;
+                    case ERROR : dispatcherMapping = INCLUDE_ERROR; break;
+                    case FORWARD  :  dispatcherMapping = INCLUDE_FORWARD; break;
+                    case FORWARD_ERROR  :  dispatcherMapping = INCLUDE_ERROR_FORWARD; break;
+                    case REQUEST : dispatcherMapping = REQUEST_INCLUDE; break;
+                    case REQUEST_ERROR : dispatcherMapping = REQUEST_ERROR_INCLUDE; break;
+                    case REQUEST_ERROR_FORWARD : dispatcherMapping = REQUEST_ERROR_FORWARD_INCLUDE; break;
+                    case REQUEST_FORWARD : dispatcherMapping = REQUEST_FORWARD_INCLUDE; break;
+                }
+            } else if (dispatcher.equals("REQUEST")) {
+                // apply REQUEST to the global dispatcherMapping.
+                switch (dispatcherMapping) {
+                    case NOT_SET  :  dispatcherMapping = REQUEST; break;
+                    case ERROR : dispatcherMapping = REQUEST_ERROR; break;
+                    case FORWARD  :  dispatcherMapping = REQUEST_FORWARD; break;
+                    case FORWARD_ERROR  :  dispatcherMapping = REQUEST_ERROR_FORWARD; break;
+                    case INCLUDE  :  dispatcherMapping = REQUEST_INCLUDE; break;
+                    case INCLUDE_ERROR  :  dispatcherMapping = REQUEST_ERROR_INCLUDE; break;
+                    case INCLUDE_FORWARD : dispatcherMapping = REQUEST_FORWARD_INCLUDE; break;
+                    case INCLUDE_ERROR_FORWARD : dispatcherMapping = REQUEST_ERROR_FORWARD_INCLUDE; break;
+                }
+            }  else if (dispatcher.equals("ERROR")) {
+                // apply ERROR to the global dispatcherMapping.
+                switch (dispatcherMapping) {
+                    case NOT_SET  :  dispatcherMapping = ERROR; break;
+                    case FORWARD  :  dispatcherMapping = FORWARD_ERROR; break;
+                    case INCLUDE  :  dispatcherMapping = INCLUDE_ERROR; break;
+                    case INCLUDE_FORWARD : dispatcherMapping = INCLUDE_ERROR_FORWARD; break;
+                    case REQUEST : dispatcherMapping = REQUEST_ERROR; break;
+                    case REQUEST_INCLUDE : dispatcherMapping = REQUEST_ERROR_INCLUDE; break;
+                    case REQUEST_FORWARD : dispatcherMapping = REQUEST_ERROR_FORWARD; break;
+                    case REQUEST_FORWARD_INCLUDE : dispatcherMapping = REQUEST_ERROR_FORWARD_INCLUDE; break;
+                }
+            }
+        }
+        
+        public int getDispatcherMapping() {
+            // per the SRV.6.2.5 absence of any dispatcher elements is
+            // equivelant to a REQUEST value
+            if (dispatcherMapping == NOT_SET) return REQUEST;
+            else return dispatcherMapping; 
+        }
+
+    }
+
+
+    public void init(FilterConfig filterConfig) throws ServletException {
+    }
+
+
+    public void doFilter(ServletRequest request, ServletResponse response, 
+                         FilterChain chain) 
+            throws IOException, ServletException {
+    }
+
+
+    public void destroy() {
+    }
+
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Mime
View raw message