You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by co...@apache.org on 2009/04/04 18:24:36 UTC

svn commit: r761964 [5/10] - in /tomcat/trunk/modules/tomcat-lite/java: ./ org/ org/apache/ org/apache/tomcat/ org/apache/tomcat/addons/ org/apache/tomcat/integration/ org/apache/tomcat/integration/jmx/ org/apache/tomcat/integration/simple/ org/apache/...

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,642 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.lite;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.Filter;
+import javax.servlet.Servlet;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.UnavailableException;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.tomcat.integration.ObjectManager;
+import org.apache.tomcat.integration.simple.SimpleObjectManager;
+import org.apache.tomcat.util.buf.MessageBytes;
+import org.apache.tomcat.util.buf.UriNormalizer;
+import org.apache.tomcat.util.http.mapper.MappingData;
+
+/**
+ * Simpler, lower footprint serlvet engine.  
+ * 
+ * Uses ObjectManager to integate with an embedding app 
+ * - the object names it uses:
+ * 
+ * Internal objects created by Tomcat and registered for management 
+ * and injection: 
+ * - Servlet:CONTEXT_PATH:SERVLETNAME - a ServletWrapper
+ * - ServletContext:CONTEXT_PATH
+ * - ProtocolHandler:ep-PORT - coyote ProtocolHandler
+ * - CoyoteServer:CoyoteServer-PORT
+ * - CoyoteAdapter:PATH - for the coyote used Adapter 
+ * - TomcatLite - this object.
+ * - Connector - the connector object
+ * 
+ * Plugins to be constructed by framework ( defaults set in initDefaults ):
+ * - UserSessionManager
+ * - UserTemplateClassMapper
+ * - ContextPreinitListener
+ * - Connector
+ * - WebappServletMapper
+ * - WebappFilterMapper
+ * - default-servlet  
+ * - jspwildcard-servlet
+ * - Foo-servlet - servlet named Foo
+ * 
+ * 
+ * @author Costin Manolache
+ */
+public class TomcatLite implements Runnable {
+
+    private String serverDirName;
+    private File workDir;
+    
+    // all contexts - hostMapper knows about hostnames and how they are mapped.
+    // this shouldn't be needed if we want to delegate ctx management
+    private ArrayList<ServletContextImpl> contexts = new ArrayList();
+
+    URLClassLoader contextParentLoader;
+    
+    // Discovered or default Host/Context mapper
+    Filter hostMapper;
+
+    // Servlets to preload in each context, configurable from CLI or API
+    Map<String,String> preloadServlets = new HashMap();
+    Map<String,String> preloadMappings = new HashMap();
+    
+    Map<String,String> ctxDefaultInitParam = new HashMap();
+        
+    Connector coyoteAdapter;
+    
+    ObjectManager om;
+    
+    static String SERVLETS_PACKAGE = "org.apache.tomcat.servlets";
+    
+    
+    protected boolean daemon = false;
+    
+    public TomcatLite() {
+    }
+
+    public TomcatLite(ObjectManager om) {
+        this.setObjectManager(om);
+    }
+
+    // --------------- start/stop ---------------
+    
+    /**
+     * Return the object manager associated with this tomcat.
+     * If none set, create a minimal one with the default 
+     * values.
+     */
+    public ObjectManager getObjectManager() {
+        if (om == null) {
+            // Defaults.
+            om = new ObjectManager();
+            SimpleObjectManager props = new SimpleObjectManager(om);
+            // Init defaults. If using a custom OM, you should register 
+            // at the default objects as well.
+            props.loadResource("org/apache/tomcat/lite/config.properties");
+        }
+        return om;
+    }
+    
+    public void setObjectManager(ObjectManager om) {
+        this.om = om;
+    }
+    
+    public List/*<ServletContextImpl>*/ getWebapps() {
+        return contexts;
+    }
+    
+    public URLClassLoader getContextParentLoader() {
+        if (contextParentLoader == null) {
+            
+            ClassLoader parent = this.getClass().getClassLoader();
+            contextParentLoader = new URLClassLoader(new URL[] {},
+                    parent);
+            
+            /*if (engineRepo == null) {
+                engineRepo = new Repository();
+                engineRepo.setParentClassLoader(parent);
+            }
+            
+            contextParentLoader = 
+                engineRepo.getClassLoader();
+            */
+        }
+        return contextParentLoader;
+    }
+        
+    public void start() throws IOException {
+        long t0 = System.currentTimeMillis();
+        
+        // start all contexts
+        // init all contexts
+        Iterator i1 = contexts.iterator();
+        while (i1.hasNext()) {
+           ServletContextImpl ctx = (ServletContextImpl) i1.next();
+           try {
+               ctx.start();
+           } catch (Throwable e) {
+               e.printStackTrace();
+           }
+        }
+        long t1 = System.currentTimeMillis();
+        System.err.println("Engine.start() " + (t1-t0));
+    }
+    
+      
+    /**
+     * Add a context - used for IntrospectionUtils.
+     * 
+     * ContextPath:ContextBaseDir
+     */
+    public void setContext(String c) throws ServletException {
+        String[] pathDir = c.split(":", 2);
+        addServletContext("", pathDir[1], pathDir[0]);
+    }
+    
+    public void setServletContexts(List<ServletContext> c) throws ServletException {
+        for (ServletContext ctx: c) {
+            addServletContext((ServletContextImpl) ctx);
+        }
+    }
+    
+    public void setPreload(String servletNameClass) {
+        String[] nv = servletNameClass.split(":");
+        preloadServlets.put(nv[0], nv[1]);
+    }
+    
+    public void addPreload(String servletName, String servletClassName) {
+        preloadServlets.put(servletName, servletClassName);
+    }
+
+    public void setDefaultInitParam(String nameValue) {
+        String[] nv = nameValue.split(":");
+        ctxDefaultInitParam.put(nv[0], nv[1]);
+    }
+    
+    public void addDefaultInitParam(String name, String value) {
+        ctxDefaultInitParam.put(name, value);
+    }
+    
+    public void setPreloadMappings(String servletPath) {
+        String[] nv = servletPath.split(":");
+        preloadMappings.put(nv[0], nv[1]);
+    }
+    
+    public void addPreloadMapping(String servletName, String path) {
+        preloadMappings.put(servletName, path);
+    }
+    
+    public void stop() {
+        Iterator i1 = contexts.iterator();
+        while (i1.hasNext()) {
+           ServletContextImpl ctx = (ServletContextImpl) i1.next();
+            try {
+                ctx.destroy();
+            } catch (Throwable e) {
+                e.printStackTrace();
+            }
+        }
+        stopConnector();
+    }
+
+    // -------------- Context add/remove --------------
+
+    public static String[] DEFAULT_WELCOME = { "index.html" };
+    
+    public void addServletContext(ServletContextImpl ctx) throws ServletException {
+        ctx.setTomcat(this);
+        if (hostMapper == null) { 
+            hostMapper = new WebappContextMapper();
+        }
+
+        ((WebappContextMapper) hostMapper).addHost(ctx.getHostname(), null);
+        ((WebappContextMapper) hostMapper).addContext(ctx.getHostname(), 
+                ctx);
+
+        contexts.add(ctx);
+        
+        getObjectManager().bind("ServletContext:" + ctx.getContextPath(), 
+                ctx);
+
+    }
+    
+    /**
+     * Add a context. 
+     * 
+     * web.xml will be read as part of init, and the initialization will be 
+     * part of start or lazy.
+     * 
+     * @param hostname - ""
+     *            if default host, or string to be matched with Host header
+     * @param basePath = directory where the webapp is installed           
+     * @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);
+        addServletContext(ctx);
+        return ctx;
+    }
+    
+    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
+        notifyRemove(ctx);
+    }
+    
+    
+    /** 
+     * Required for ServletContext.getContext(uri);
+     * @throws ServletException 
+     * @throws IOException 
+     */
+    public ServletContextImpl getContext(ServletContextImpl impl, String uri) 
+            throws IOException, ServletException {
+        // Create a request - needs to be simplified
+        ServletRequestImpl req = createMessage(impl, impl.contextPath, uri);
+        hostMapper.doFilter(req, null, null);
+        return req.getContext();
+    }
+    
+    public ServletResponseImpl service(ServletRequestImpl req) throws IOException, Exception {
+      ServletResponseImpl res = req.getResponse();
+      service(req, res);
+      endRequest(req, res);
+      return res;
+    }
+    
+    public void service(ServletRequestImpl req, ServletResponseImpl res) 
+            throws Exception, IOException {
+        // parse the session id from URI
+        req.parseSessionId();
+        
+        try {
+          UriNormalizer.decodeRequest(req.getCoyoteRequest().decodedURI(), 
+                  req.getCoyoteRequest().requestURI(),
+                  req.getCoyoteRequest().getURLDecoder());
+        } catch(IOException ioe) {
+            res.setStatus(400);
+            return;
+        }
+        
+        MappingData mapRes = req.getMappingData();
+        try {
+          // TODO: make hostMapper configurable, implement interface,
+          // simple to set on ROOT context
+          hostMapper.doFilter(req, null, null);
+            
+
+          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.getCoyoteRequest().decodedURI(), mapRes);
+
+          // Possible redirect
+          MessageBytes redirectPathMB = mapRes.redirectPath;
+          if (!redirectPathMB.isNull()) {
+              String redirectPath = res.urlEncoder.encodeURL(redirectPathMB.toString());
+              String query = req.getQueryString();
+              if (req.isRequestedSessionIdFromURL()) {
+                  // This is not optimal, but as this is not very common, it
+                  // shouldn't matter
+                  redirectPath = redirectPath + ";" + ServletRequestImpl.SESSION_PARAMETER_NAME + "=" 
+                      + req.getRequestedSessionId();
+              }
+              if (query != null) {
+                  // This is not optimal, but as this is not very common, it
+                  // shouldn't matter
+                  redirectPath = redirectPath + "?" + query;
+              }
+              res.sendRedirect(redirectPath);
+              return;
+          }
+          
+          req.parseSessionCookiesId();
+
+          ServletConfigImpl h=(ServletConfigImpl)mapRes.wrapper;
+          if (h != null) {
+            req.setWrapper((ServletConfigImpl)mapRes.wrapper);
+            serviceServlet(ctx, req, res, h, mapRes );
+            // send the response...
+
+            //res.flushBuffer();
+
+            // Recycle the wrapper request and response
+            //req.recycle();
+            //res.recycle();
+          }
+        } 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 
+     */
+    private void serviceServlet(ServletContextImpl ctx, 
+                               ServletRequestImpl req, 
+                               ServletResponseImpl res,
+                               ServletConfigImpl servletConfig, 
+                               MappingData mapRes) 
+            throws IOException {
+        Servlet servlet = null;
+        try {
+            if (servletConfig.isUnavailable()) {
+                handleUnavailable(res, servletConfig);
+                return;
+            }
+            try {
+                servlet = servletConfig.allocate();
+            } catch(ServletException ex) {
+                handleUnavailable(res, servletConfig);
+            }
+            WebappFilterMapper filterMap = ctx.getFilterMapper();
+            FilterChainImpl chain = 
+                filterMap.createFilterChain(req, servletConfig, servlet);
+            
+            try {
+                if (chain == null) {
+                    if (servlet != null) {
+                        servlet.service(req, res);
+                    } else {
+                        System.err.println("No servlet " + req.getRequestURI());
+                        res.sendError(404);
+                    }
+                } else {
+                    chain.doFilter(req, res);
+                }
+            } catch(UnavailableException ex) {
+                servletConfig.unavailable(ex);
+                handleUnavailable(res, servletConfig);
+                return;
+            }
+            
+            // servlet completed without exception. Check status
+            int status = res.getStatus();
+            if (status != 200 && !res.isCommitted()) {
+                String statusPage = ctx.findStatusPage(status);
+
+                if (statusPage != null) {
+                    ctx.handleStatusPage(req, res, status, statusPage);
+                } else {
+                    // Send a default message body.
+                    // TODO: maybe other mechanism to customize default.
+                    res.defaultStatusPage(status, res.getMessage());
+                }
+            }
+        } catch (Throwable t) {
+            ctx.handleError(req, res, t);
+        } finally {
+            if (servlet != null) {
+                servletConfig.deallocate(servlet);
+            }
+        }
+    }
+
+    private void handleUnavailable(ServletResponseImpl response, 
+                                   ServletConfigImpl servletConfig) 
+            throws IOException {
+        long available = servletConfig.getAvailable();
+        if ((available > 0L) && (available < Long.MAX_VALUE))
+            response.setDateHeader("Retry-After", available);
+        //  TODO: handle via error pages !
+        response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, 
+                "Service unavailable");
+    }
+    
+
+    // ------------ Notifications for JMX ----------------
+
+    void notifyAdd(Object o) {
+    }
+
+    void notifyRemove(Object o) {
+    }
+
+    public void setServerDir(String dir) {
+      this.serverDirName = dir;
+    }
+        
+    public File getWork() {
+        if (workDir == null) {
+          if (serverDirName == null) {
+              serverDirName = "./";
+          }
+          File rootDirFile = new File(serverDirName);
+          workDir = new File(rootDirFile, "tomcat-work");
+          if (workDir.exists()) {
+            workDir.mkdirs();
+          }
+        }
+        return workDir;
+    }
+    
+    /** 
+     * Init
+     * 
+     * @throws ServletException
+     * @throws IOException
+     */
+    public void init() throws ServletException, IOException {
+      getObjectManager().bind("TomcatLite", this);
+      if (contexts.size() == 0) {
+        setContext("/:./webapps/ROOT");
+      }
+      getConnector().setObjectManager(getObjectManager());
+      Iterator i1 = contexts.iterator();
+      while (i1.hasNext()) {
+        ServletContextImpl ctx = (ServletContextImpl) i1.next();
+        try {
+          ctx.init();
+        } catch (Throwable e) {
+          e.printStackTrace();
+        }
+      }
+    }
+    
+    /**
+     * Initialize an webapp and add it to the server. 
+     * - load web.xml
+     * - call 
+     * 
+     * @param rootDir
+     * @param path
+     * @param deployServlet
+     */
+    public void init(String rootDir, String path) 
+            throws ServletException, IOException {
+        
+        long t0 = System.currentTimeMillis();
+
+        ServletContextImpl ctx = 
+            (ServletContextImpl)addServletContext(null, 
+                                                  rootDir, 
+                                                  path);
+        ctx.init();
+        
+        long t1 = System.currentTimeMillis();
+        
+        // At this point all config is loaded. Contexts are not yet init()
+        // - this will happen on start.
+        System.err.println("Context.init() " + path + " " + (t1-t0));
+    }
+
+    /** 
+     * Get an empty request/response pair ( response available 
+     * as getResponse() ). Optional set input and output buffers.
+     * 
+     * This can be used for a connector-less interface to tomcat lite.
+     * 
+     * TODO: make it independent of coyote !
+     */
+    
+    public  ServletRequestImpl createMessage() {
+      ServletRequestImpl req = new ServletRequestImpl();
+      ServletResponseImpl res = req.getResponse();
+      
+      getConnector().initRequest(req, res);
+      
+      req.getCoyoteRequest().method().setString("GET");
+      req.getCoyoteRequest().protocol().setString("HTTP/1.1");
+      
+      return req;
+    }
+    
+    /**
+     * Used internally for mapping. 
+     */
+    private ServletRequestImpl createMessage(ServletContextImpl deployCtx,
+                                            String ctxPath,
+                                            String reqPath) {
+      ServletRequestImpl req = createMessage();
+      req.setContextPath(ctxPath);
+      req.setContext(deployCtx);
+      req.setRequestURI(ctxPath + reqPath);
+      return req;
+    }
+    
+
+    /** 
+     * Set a global filter that will be used for context mapping.
+     * 
+     * The filter will get a request, with requestUri and hostname set.
+     *  
+     * It needs to compute the context path and set it as an attribute.
+     * 
+     * Advanced features may include on-demand loading of webapps, large scale
+     * virtual hosting, etc.
+     */
+    public void setContextMapper(Filter hostMapper2) {
+        this.hostMapper = hostMapper2;
+    }
+
+    public void endRequest(ServletRequestImpl req,
+                           ServletResponseImpl res) throws IOException {
+     res.outputBuffer.flush();
+     res.getCoyoteResponse().finish();
+    }
+    
+    public Connector getConnector() {
+        if (coyoteAdapter == null) {
+            coyoteAdapter = (Connector) getObjectManager().get(Connector.class);
+            setConnector(coyoteAdapter);
+        }
+        return coyoteAdapter;
+    }
+
+    public void setConnector(Connector c) {
+        coyoteAdapter = c;
+        coyoteAdapter.setTomcatLite(this);
+        getObjectManager().bind("Connector", coyoteAdapter);
+    }
+
+    
+    public void setDaemon(boolean d) {
+        getConnector();
+        if (coyoteAdapter != null) {
+            coyoteAdapter.setDaemon(d);
+        }
+    }
+
+    public void startConnector() {
+        getConnector();
+        if (coyoteAdapter != null) {
+            coyoteAdapter.start();
+        }
+    }
+
+    public void stopConnector() {
+        getConnector();
+        if (coyoteAdapter != null) {
+            coyoteAdapter.stop();
+        }
+    }
+
+    public void run() {
+        try {
+            execute();
+        } catch (ServletException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+    
+    public void execute() throws ServletException, IOException {
+        init();
+        start();
+        startConnector();
+    }
+}

Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappContextMapper.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappContextMapper.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappContextMapper.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappContextMapper.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,132 @@
+package org.apache.tomcat.lite;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+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 org.apache.tomcat.util.buf.CharChunk;
+import org.apache.tomcat.util.buf.MessageBytes;
+import org.apache.tomcat.util.http.mapper.MappingData;
+
+/** 
+ * This handles host and context mapping.
+ * 
+ * The default implementation for tomcat lite is very limitted - 
+ * no support for virtual hosts, no support for contexts deeper than 
+ * 1 level. The intention is to override this with more advanced mappers.
+ * 
+ * With 'ConfigurableHosts' interface it is possible for a smart 
+ * mapper to load/unload virtual hosts at runtime, maybe from a 
+ * database. It should be possible to use databases to store huge number 
+ * of hosts or webapps. 
+ * 
+ */
+public class WebappContextMapper implements Filter {
+
+  ServletContext rootContext;
+  Map<MessageBytes, ServletContext> contexts = new HashMap();
+
+  public WebappContextMapper() {
+  }
+
+  public void addHost(String name, String[] aliases) {
+  }
+  
+  /**
+   * 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, 
+                         ServletContext context)
+      throws ServletException
+  {
+    String path = context.getContextPath();
+    if (path.lastIndexOf("/") > 0) {
+      throw new ServletException("Base context mapper supports only one level");
+    }
+    if ("/".equals(path)) {
+      rootContext = context;
+    }
+    MessageBytes mb = MessageBytes.newInstance();
+    mb.setChars(path.toCharArray(), 0, path.length());
+    contexts.put(mb, context);
+  }
+
+
+  /**
+   * 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 {
+    if ("/".equals(path)) {
+      rootContext = null;
+    }
+    contexts.remove(path);  
+  }
+
+  /**
+   * Map the specified URI.
+   */
+  private void mapContext(ServletRequestImpl req)
+      throws IOException, ServletException {
+    MessageBytes uriMB = req.getDecodedRequestURIMB();
+    MappingData mappingData = req.getMappingData(); 
+    uriMB.toChars();
+    CharChunk uri = uriMB.getCharChunk();
+
+    
+    if (uri.length() < 2 || contexts.size() == 0) {
+      mappingData.context = rootContext;
+      if (rootContext != null) {
+        mappingData.contextPath.setString(rootContext.getContextPath());
+      }
+      return;
+    }
+    
+    int nextSlash = uri.indexOf('/', 1);
+    if (nextSlash == -1) {
+      nextSlash = uri.length();
+    }
+    mappingData.contextPath.setChars(uri.getChars(), 0, nextSlash);
+    ServletContext servletContext = contexts.get(mappingData.contextPath);
+
+    if (servletContext != null) {
+      mappingData.context = servletContext;
+    } else {
+      mappingData.context = rootContext;
+      if (rootContext != null) {
+        mappingData.contextPath.setString(rootContext.getContextPath());      
+      }
+    }
+  }
+
+  public void init(FilterConfig filterConfig) throws ServletException {
+  }
+    
+  public void doFilter(ServletRequest request, 
+                       ServletResponse response, 
+                       FilterChain chain) 
+      throws IOException, ServletException {
+    ServletRequestImpl req = (ServletRequestImpl)request;
+    mapContext(req);
+  }
+    
+  public void destroy() {
+  }
+}
\ No newline at end of file

Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappContextMapper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappFilterMapper.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappFilterMapper.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappFilterMapper.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappFilterMapper.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,529 @@
+/*
+ * 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;
+
+
+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.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() {
+    }
+
+}

Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappFilterMapper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappServletMapper.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappServletMapper.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappServletMapper.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappServletMapper.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,883 @@
+/*
+ *  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;
+
+import java.io.File;
+import java.io.IOException;
+
+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.util.buf.Ascii;
+import org.apache.tomcat.util.buf.CharChunk;
+import org.apache.tomcat.util.buf.MessageBytes;
+import org.apache.tomcat.util.http.mapper.MappingData;
+
+/**
+ * Mapper, which implements the servlet API mapping rules (which are derived
+ * from the HTTP rules).
+ * 
+ * Based on catalina mapper - but simplified. All host and context mappings
+ * is done in HostMapper - this is just dealing with web.xml.
+ * 
+ * For corner cases ( very large number of rules, dynamic rules, etc ) you 
+ * can override the mapper for a context with a class extending this.
+ * 
+ * TODO: remove, use coyote-level mapper or user-space
+ */
+public class WebappServletMapper implements Filter {
+
+    /**
+     * Context associated with this wrapper, used for wrapper mapping.
+     */
+    public ContextMapElement contextMapElement = new ContextMapElement();
+
+
+    // --------------------------------------------------------- Public Methods
+    public WebappServletMapper() {
+    }
+    
+    public void setServletContext(ServletContextImpl impl) {
+        contextMapElement.object = impl;
+        contextMapElement.name = impl.getContextPath();        
+    }
+
+
+   /** Set context, used for wrapper mapping (request dispatcher).
+     *
+     * @param welcomeResources Welcome files defined for this context
+     * @param resources Static resources of the context
+     */
+    public void setContext(String path, String[] welcomeResources,
+                           File resources) {
+        contextMapElement.name = path;
+        contextMapElement.welcomeResources = welcomeResources;
+        contextMapElement.resources = resources;
+    }
+
+
+    /**
+     * Add a wrapper to the context associated with this wrapper.
+     *
+     * @param path Wrapper mapping
+     * @param wrapper The Wrapper object
+     */
+    public void addWrapper(String path, Object wrapper) {
+        addWrapper(contextMapElement, path, wrapper);
+    }
+
+
+    public void addWrapper(String path, Object wrapper, boolean jspWildCard) {
+        addWrapper(contextMapElement, path, wrapper, jspWildCard);
+    }
+
+
+    public void addWrapper(ContextMapElement context, String path, Object wrapper) {
+        addWrapper(context, path, wrapper, false);
+    }
+
+
+    /**
+     * Adds a wrapper to the given context.
+     *
+     * @param context The context to which to add the wrapper
+     * @param path Wrapper mapping
+     * @param wrapper The Wrapper object
+     * @param jspWildCard true if the wrapper corresponds to the JspServlet
+     * and the mapping path contains a wildcard; false otherwise
+     */
+    protected void addWrapper(ContextMapElement context, String path, Object wrapper,
+                              boolean jspWildCard) {
+
+        synchronized (context) {
+            WrapperMapElement newWrapper = new WrapperMapElement();
+            newWrapper.object = wrapper;
+            newWrapper.jspWildCard = jspWildCard;
+            if (path.endsWith("/*")) {
+                // Wildcard wrapper
+                newWrapper.name = path.substring(0, path.length() - 2);
+                WrapperMapElement[] oldWrappers = context.wildcardWrappers;
+                WrapperMapElement[] newWrappers =
+                    new WrapperMapElement[oldWrappers.length + 1];
+                if (insertMap(oldWrappers, newWrappers, newWrapper)) {
+                    context.wildcardWrappers = newWrappers;
+                    int slashCount = slashCount(newWrapper.name);
+                    if (slashCount > context.nesting) {
+                        context.nesting = slashCount;
+                    }
+                }
+            } else if (path.startsWith("*.")) {
+                // Extension wrapper
+                newWrapper.name = path.substring(2);
+                WrapperMapElement[] oldWrappers = context.extensionWrappers;
+                WrapperMapElement[] newWrappers =
+                    new WrapperMapElement[oldWrappers.length + 1];
+                if (insertMap(oldWrappers, newWrappers, newWrapper)) {
+                    context.extensionWrappers = newWrappers;
+                }
+            } else if (path.equals("/")) {
+                // Default wrapper
+                newWrapper.name = "";
+                context.defaultWrapper = newWrapper;
+            } else {
+                // Exact wrapper
+                newWrapper.name = path;
+                WrapperMapElement[] oldWrappers = context.exactWrappers;
+                WrapperMapElement[] newWrappers =
+                    new WrapperMapElement[oldWrappers.length + 1];
+                if (insertMap(oldWrappers, newWrappers, newWrapper)) {
+                    context.exactWrappers = newWrappers;
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Remove a wrapper from the context associated with this wrapper.
+     *
+     * @param path Wrapper mapping
+     */
+    public void removeWrapper(String path) {
+        removeWrapper(contextMapElement, path);
+    }
+
+
+    protected void removeWrapper(ContextMapElement context, String path) {
+        synchronized (context) {
+            if (path.endsWith("/*")) {
+                // Wildcard wrapper
+                String name = path.substring(0, path.length() - 2);
+                WrapperMapElement[] oldWrappers = context.wildcardWrappers;
+                WrapperMapElement[] newWrappers =
+                    new WrapperMapElement[oldWrappers.length - 1];
+                if (removeMap(oldWrappers, newWrappers, name)) {
+                    // Recalculate nesting
+                    context.nesting = 0;
+                    for (int i = 0; i < newWrappers.length; i++) {
+                        int slashCount = slashCount(newWrappers[i].name);
+                        if (slashCount > context.nesting) {
+                            context.nesting = slashCount;
+                        }
+                    }
+                    context.wildcardWrappers = newWrappers;
+                }
+            } else if (path.startsWith("*.")) {
+                // Extension wrapper
+                String name = path.substring(2);
+                WrapperMapElement[] oldWrappers = context.extensionWrappers;
+                WrapperMapElement[] newWrappers =
+                    new WrapperMapElement[oldWrappers.length - 1];
+                if (removeMap(oldWrappers, newWrappers, name)) {
+                    context.extensionWrappers = newWrappers;
+                }
+            } else if (path.equals("/")) {
+                // Default wrapper
+                context.defaultWrapper = null;
+            } else {
+                // Exact wrapper
+                String name = path;
+                WrapperMapElement[] oldWrappers = context.exactWrappers;
+                WrapperMapElement[] newWrappers =
+                    new WrapperMapElement[oldWrappers.length - 1];
+                if (removeMap(oldWrappers, newWrappers, name)) {
+                    context.exactWrappers = newWrappers;
+                }
+            }
+        }
+    }
+
+    /**
+     * Map the specified URI relative to the context,
+     * mutating the given mapping data.
+     *
+     * @param uri URI
+     * @param mappingData This structure will contain the result of the mapping
+     *                    operation
+     */
+    public void map(MessageBytes uri, MappingData mappingData)
+        throws Exception {
+
+        uri.toChars();
+        CharChunk uricc = uri.getCharChunk();
+        //uricc.setLimit(-1);
+        internalMapWrapper(contextMapElement, uricc, mappingData);
+
+    }
+
+
+    // -------------------------------------------------------- Private Methods
+
+
+    /**
+     * Wrapper mapping.
+     */
+    private final void internalMapWrapper(ContextMapElement context,
+                                          CharChunk path,
+                                          MappingData mappingData)
+        throws Exception {
+
+        int pathOffset = path.getOffset();
+        int pathEnd = path.getEnd();
+        int servletPath = pathOffset;
+        boolean noServletPath = false;
+
+        int length = context.name.length();
+        if (length == 1) length--;
+        if (length != (pathEnd - pathOffset)) {
+            servletPath = pathOffset + length;
+        } else {
+            noServletPath = true;
+            // What is this doing ??? 
+            path.append('/');
+            pathOffset = path.getOffset();
+            pathEnd = path.getEnd();
+            servletPath = pathOffset+length;
+        }
+
+        path.setOffset(servletPath);
+
+        // Rule 1 -- Exact Match
+        WrapperMapElement[] exactWrappers = context.exactWrappers;
+        internalMapExactWrapper(exactWrappers, path, mappingData);
+
+        // Rule 2 -- Prefix Match
+        boolean checkJspWelcomeFiles = false;
+        WrapperMapElement[] wildcardWrappers = context.wildcardWrappers;
+        if (mappingData.wrapper == null) {
+            internalMapWildcardWrapper(wildcardWrappers, context.nesting, 
+                                       path, mappingData);
+            if (mappingData.wrapper != null && mappingData.jspWildCard) {
+                char[] buf = path.getBuffer();
+                if (buf[pathEnd - 1] == '/') {
+                    /*
+                     * Path ending in '/' was mapped to JSP servlet based on
+                     * wildcard match (e.g., as specified in url-pattern of a
+                     * jsp-property-group.
+                     * Force the context's welcome files, which are interpreted
+                     * as JSP files (since they match the url-pattern), to be
+                     * considered. See Bugzilla 27664.
+                     */ 
+                    mappingData.wrapper = null;
+                    checkJspWelcomeFiles = true;
+                } else {
+                    // See Bugzilla 27704
+                    mappingData.wrapperPath.setChars(buf, path.getStart(),
+                                                     path.getLength());
+                    mappingData.pathInfo.recycle();
+                }
+            }
+        }
+
+        if(mappingData.wrapper == null && noServletPath) {
+            // The path is empty, redirect to "/"
+            mappingData.redirectPath.setChars
+                (path.getBuffer(), pathOffset, pathEnd);
+            path.setEnd(pathEnd - 1);
+            return;
+        }
+
+        // Rule 3 -- Extension Match
+        WrapperMapElement[] extensionWrappers = context.extensionWrappers;
+        if (mappingData.wrapper == null && !checkJspWelcomeFiles) {
+            internalMapExtensionWrapper(extensionWrappers, path, mappingData);
+        }
+
+        File file = null;
+        // Rule 4 -- Welcome resources processing for servlets
+        if (mappingData.wrapper == null) {
+            boolean checkWelcomeFiles = checkJspWelcomeFiles;
+            if (!checkWelcomeFiles) {
+                char[] buf = path.getBuffer();
+                checkWelcomeFiles = (buf[pathEnd - 1] == '/');
+            }
+            if (checkWelcomeFiles) {
+                for (int i = 0; (i < context.welcomeResources.length)
+                         && (mappingData.wrapper == null); i++) {
+                    path.setOffset(pathOffset);
+                    path.setEnd(pathEnd);
+                    path.append(context.welcomeResources[i], 0,
+                                context.welcomeResources[i].length());
+                    path.setOffset(servletPath);
+
+                    // Rule 4a -- Welcome resources processing for exact macth
+                    internalMapExactWrapper(exactWrappers, path, mappingData);
+
+                    // Rule 4b -- Welcome resources processing for prefix match
+                    if (mappingData.wrapper == null) {
+                        internalMapWildcardWrapper
+                            (wildcardWrappers, context.nesting, 
+                             path, mappingData);
+                    }
+
+                    // Rule 4c -- Welcome resources processing
+                    //            for physical folder
+                    if (mappingData.wrapper == null
+                        && context.resources != null) {
+                        // Default servlet: check if it's file or dir to apply
+                        // welcome files rules. 
+                        // TODO: Save the File in attributes, 
+                        // to avoid duplication in DefaultServlet.
+                        
+                        String pathStr = path.toString();
+                        file = new File(context.resources, pathStr);
+                        if (file.exists() && !(file.isDirectory()) ) {
+                            
+                            internalMapExtensionWrapper(extensionWrappers,
+                                                        path, mappingData);
+                            if (mappingData.wrapper == null
+                                && context.defaultWrapper != null) {
+                                mappingData.wrapper =
+                                    context.defaultWrapper.object;
+                                mappingData.requestPath.setChars
+                                    (path.getBuffer(), path.getStart(), 
+                                     path.getLength());
+                                mappingData.wrapperPath.setChars
+                                    (path.getBuffer(), path.getStart(), 
+                                     path.getLength());
+                                mappingData.requestPath.setString(pathStr);
+                                mappingData.wrapperPath.setString(pathStr);
+                            }
+                        }
+                    }
+                }
+
+                path.setOffset(servletPath);
+                path.setEnd(pathEnd);
+            }
+                                        
+        }
+
+
+        // Rule 7 -- Default servlet
+        if (mappingData.wrapper == null && !checkJspWelcomeFiles) {
+            if (context.defaultWrapper != null) {
+                mappingData.wrapper = context.defaultWrapper.object;
+                mappingData.requestPath.setChars
+                    (path.getBuffer(), path.getStart(), path.getLength());
+                mappingData.wrapperPath.setChars
+                    (path.getBuffer(), path.getStart(), path.getLength());
+            }
+            // Redirection to a folder
+            char[] buf = path.getBuffer();
+            if (context.resources != null && buf[pathEnd -1 ] != '/') {
+                String pathStr = path.toString();
+                file = new File( context.resources, pathStr);
+                if (file.exists() && file.isDirectory()) {
+                    // Note: this mutates the path: do not do any processing 
+                    // after this (since we set the redirectPath, there 
+                    // shouldn't be any)
+                    path.setOffset(pathOffset);
+                    path.append('/');
+                    mappingData.redirectPath.setChars
+                        (path.getBuffer(), path.getStart(), path.getLength());
+                } else {
+                    mappingData.requestPath.setString(pathStr);
+                    mappingData.wrapperPath.setString(pathStr);
+                }
+            }
+        }
+
+        path.setOffset(pathOffset);
+        path.setEnd(pathEnd);
+    }
+
+
+    /**
+     * Exact mapping.
+     */
+    private final void internalMapExactWrapper
+        (WrapperMapElement[] wrappers, CharChunk path, MappingData mappingData) {
+        int pos = find(wrappers, path);
+        if ((pos != -1) && (path.equals(wrappers[pos].name))) {
+            mappingData.requestPath.setString(wrappers[pos].name);
+            mappingData.wrapperPath.setString(wrappers[pos].name);
+            mappingData.wrapper = wrappers[pos].object;
+        }
+    }
+
+
+    /**
+     * Wildcard mapping.
+     */
+    private final void internalMapWildcardWrapper
+        (WrapperMapElement[] wrappers, int nesting, CharChunk path, 
+         MappingData mappingData) {
+
+        int pathEnd = path.getEnd();
+        int pathOffset = path.getOffset();
+
+        int lastSlash = -1;
+        int length = -1;
+        int pos = find(wrappers, path);
+        if (pos != -1) {
+            boolean found = false;
+            while (pos >= 0) {
+                if (path.startsWith(wrappers[pos].name)) {
+                    length = wrappers[pos].name.length();
+                    if (path.getLength() == length) {
+                        found = true;
+                        break;
+                    } else if (path.startsWithIgnoreCase("/", length)) {
+                        found = true;
+                        break;
+                    }
+                }
+                if (lastSlash == -1) {
+                    lastSlash = nthSlash(path, nesting + 1);
+                } else {
+                    lastSlash = lastSlash(path);
+                }
+                path.setEnd(lastSlash);
+                pos = find(wrappers, path);
+            }
+            path.setEnd(pathEnd);
+            if (found) {
+                mappingData.wrapperPath.setString(wrappers[pos].name);
+                if (path.getLength() > length) {
+                    mappingData.pathInfo.setChars
+                        (path.getBuffer(),
+                         path.getOffset() + length,
+                         path.getLength() - length);
+                }
+                mappingData.requestPath.setChars
+                    (path.getBuffer(), path.getOffset(), path.getLength());
+                mappingData.wrapper = wrappers[pos].object;
+                mappingData.jspWildCard = wrappers[pos].jspWildCard;
+            }
+        }
+    }
+
+
+    /**
+     * Extension mappings.
+     */
+    private final void internalMapExtensionWrapper
+        (WrapperMapElement[] wrappers, CharChunk path, MappingData mappingData) {
+        char[] buf = path.getBuffer();
+        int pathEnd = path.getEnd();
+        int servletPath = path.getOffset();
+        int slash = -1;
+        for (int i = pathEnd - 1; i >= servletPath; i--) {
+            if (buf[i] == '/') {
+                slash = i;
+                break;
+            }
+        }
+        if (slash == -1 ) slash = 0;
+        if (slash >= 0) {
+            int period = -1;
+            for (int i = pathEnd - 1; i > slash; i--) {
+                if (buf[i] == '.') {
+                    period = i;
+                    break;
+                }
+            }
+            if (period >= 0) {
+                path.setOffset(period + 1);
+                path.setEnd(pathEnd);
+                int pos = find(wrappers, path);
+                if ((pos != -1)
+                    && (path.equals(wrappers[pos].name))) {
+                    mappingData.wrapperPath.setChars
+                        (buf, servletPath, pathEnd - servletPath);
+                    mappingData.requestPath.setChars
+                        (buf, servletPath, pathEnd - servletPath);
+                    mappingData.wrapper = wrappers[pos].object;
+                }
+                path.setOffset(servletPath);
+                path.setEnd(pathEnd);
+            }
+        }
+    }
+
+
+    /**
+     * Find a map elemnt given its name in a sorted array of map elements.
+     * This will return the index for the closest inferior or equal item in the
+     * given array.
+     */
+    public static final int find(MapElement[] map, CharChunk name) {
+        return find(map, name, name.getStart(), name.getEnd());
+    }
+
+
+    /**
+     * Find a map elemnt given its name in a sorted array of map elements.
+     * This will return the index for the closest inferior or equal item in the
+     * given array.
+     */
+    private static final int find(MapElement[] map, CharChunk name,
+                                  int start, int end) {
+
+        int a = 0;
+        int b = map.length - 1;
+
+        // Special cases: -1 and 0
+        if (b == -1) {
+            return -1;
+        }
+        
+        if (compare(name, start, end, map[0].name) < 0 ) {
+            return -1;
+        }         
+        if (b == 0) {
+            return 0;
+        }
+
+        int i = 0;
+        while (true) {
+            i = (b + a) / 2;
+            int result = compare(name, start, end, map[i].name);
+            if (result == 1) {
+                a = i;
+            } else if (result == 0) {
+                return i;
+            } else {
+                b = i;
+            }
+            if ((b - a) == 1) {
+                int result2 = compare(name, start, end, map[b].name);
+                if (result2 < 0) {
+                    return a;
+                } else {
+                    return b;
+                }
+            }
+        }
+
+    }
+
+    /**
+     * Find a map elemnt given its name in a sorted array of map elements.
+     * This will return the index for the closest inferior or equal item in the
+     * given array.
+     */
+    private static final int findIgnoreCase(MapElement[] map, CharChunk name) {
+        return findIgnoreCase(map, name, name.getStart(), name.getEnd());
+    }
+
+
+    /**
+     * Find a map elemnt given its name in a sorted array of map elements.
+     * This will return the index for the closest inferior or equal item in the
+     * given array.
+     */
+    private static final int findIgnoreCase(MapElement[] map, CharChunk name,
+                                  int start, int end) {
+
+        int a = 0;
+        int b = map.length - 1;
+
+        // Special cases: -1 and 0
+        if (b == -1) {
+            return -1;
+        }
+        if (compareIgnoreCase(name, start, end, map[0].name) < 0 ) {
+            return -1;
+        }         
+        if (b == 0) {
+            return 0;
+        }
+
+        int i = 0;
+        while (true) {
+            i = (b + a) / 2;
+            int result = compareIgnoreCase(name, start, end, map[i].name);
+            if (result == 1) {
+                a = i;
+            } else if (result == 0) {
+                return i;
+            } else {
+                b = i;
+            }
+            if ((b - a) == 1) {
+                int result2 = compareIgnoreCase(name, start, end, map[b].name);
+                if (result2 < 0) {
+                    return a;
+                } else {
+                    return b;
+                }
+            }
+        }
+
+    }
+
+
+    /**
+     * Find a map elemnt given its name in a sorted array of map elements.
+     * This will return the index for the closest inferior or equal item in the
+     * given array.
+     */
+    public static final int find(MapElement[] map, String name) {
+
+        int a = 0;
+        int b = map.length - 1;
+
+        // Special cases: -1 and 0
+        if (b == -1) {
+            return -1;
+        }
+        
+        if (name.compareTo(map[0].name) < 0) {
+            return -1;
+        } 
+        if (b == 0) {
+            return 0;
+        }
+
+        int i = 0;
+        while (true) {
+            i = (b + a) / 2;
+            int result = name.compareTo(map[i].name);
+            if (result > 0) {
+                a = i;
+            } else if (result == 0) {
+                return i;
+            } else {
+                b = i;
+            }
+            if ((b - a) == 1) {
+                int result2 = name.compareTo(map[b].name);
+                if (result2 < 0) {
+                    return a;
+                } else {
+                    return b;
+                }
+            }
+        }
+
+    }
+
+
+    /**
+     * Compare given char chunk with String.
+     * Return -1, 0 or +1 if inferior, equal, or superior to the String.
+     */
+    private static final int compare(CharChunk name, int start, int end,
+                                     String compareTo) {
+        int result = 0;
+        char[] c = name.getBuffer();
+        int len = compareTo.length();
+        if ((end - start) < len) {
+            len = end - start;
+        }
+        for (int i = 0; (i < len) && (result == 0); i++) {
+            if (c[i + start] > compareTo.charAt(i)) {
+                result = 1;
+            } else if (c[i + start] < compareTo.charAt(i)) {
+                result = -1;
+            }
+        }
+        if (result == 0) {
+            if (compareTo.length() > (end - start)) {
+                result = -1;
+            } else if (compareTo.length() < (end - start)) {
+                result = 1;
+            }
+        }
+        return result;
+    }
+
+
+    /**
+     * Compare given char chunk with String ignoring case.
+     * Return -1, 0 or +1 if inferior, equal, or superior to the String.
+     */
+    private static final int compareIgnoreCase(CharChunk name, int start, int end,
+                                     String compareTo) {
+        int result = 0;
+        char[] c = name.getBuffer();
+        int len = compareTo.length();
+        if ((end - start) < len) {
+            len = end - start;
+        }
+        for (int i = 0; (i < len) && (result == 0); i++) {
+            if (Ascii.toLower(c[i + start]) > Ascii.toLower(compareTo.charAt(i))) {
+                result = 1;
+            } else if (Ascii.toLower(c[i + start]) < Ascii.toLower(compareTo.charAt(i))) {
+                result = -1;
+            }
+        }
+        if (result == 0) {
+            if (compareTo.length() > (end - start)) {
+                result = -1;
+            } else if (compareTo.length() < (end - start)) {
+                result = 1;
+            }
+        }
+        return result;
+    }
+
+
+    /**
+     * Find the position of the last slash in the given char chunk.
+     */
+    public static final int lastSlash(CharChunk name) {
+
+        char[] c = name.getBuffer();
+        int end = name.getEnd();
+        int start = name.getStart();
+        int pos = end;
+
+        while (pos > start) {
+            if (c[--pos] == '/') {
+                break;
+            }
+        }
+
+        return (pos);
+
+    }
+
+
+    /**
+     * Find the position of the nth slash, in the given char chunk.
+     */
+    public static final int nthSlash(CharChunk name, int n) {
+
+        char[] c = name.getBuffer();
+        int end = name.getEnd();
+        int start = name.getStart();
+        int pos = start;
+        int count = 0;
+
+        while (pos < end) {
+            if ((c[pos++] == '/') && ((++count) == n)) {
+                pos--;
+                break;
+            }
+        }
+
+        return (pos);
+
+    }
+
+
+    /**
+     * Return the slash count in a given string.
+     */
+    public static final int slashCount(String name) {
+        int pos = -1;
+        int count = 0;
+        while ((pos = name.indexOf('/', pos + 1)) != -1) {
+            count++;
+        }
+        return count;
+    }
+
+
+    /**
+     * Insert into the right place in a sorted MapElement array, and prevent
+     * duplicates.
+     */
+    public static final boolean insertMap
+        (MapElement[] oldMap, MapElement[] newMap, MapElement newElement) {
+        int pos = find(oldMap, newElement.name);
+        if ((pos != -1) && (newElement.name.equals(oldMap[pos].name))) {
+            return false;
+        }
+        System.arraycopy(oldMap, 0, newMap, 0, pos + 1);
+        newMap[pos + 1] = newElement;
+        System.arraycopy
+            (oldMap, pos + 1, newMap, pos + 2, oldMap.length - pos - 1);
+        return true;
+    }
+
+
+    /**
+     * Insert into the right place in a sorted MapElement array.
+     */
+    public static final boolean removeMap
+        (MapElement[] oldMap, MapElement[] newMap, String name) {
+        int pos = find(oldMap, name);
+        if ((pos != -1) && (name.equals(oldMap[pos].name))) {
+            System.arraycopy(oldMap, 0, newMap, 0, pos);
+            System.arraycopy(oldMap, pos + 1, newMap, pos,
+                             oldMap.length - pos - 1);
+            return true;
+        }
+        return false;
+    }
+
+
+    // ------------------------------------------------- MapElement Inner Class
+
+
+    protected static abstract class MapElement {
+        /** hostname or path  
+         */
+        public String name = null;
+        public Object object = null;
+
+        public String toString() {
+            return "MapElement: \"" + name +"\"";
+        }
+    }
+
+
+    // ---------------------------------------------------- Context Inner Class
+
+
+    public static final class ContextMapElement
+        extends MapElement {
+
+        public String[] welcomeResources = new String[0];
+        public File resources = null;
+        public WrapperMapElement defaultWrapper = null;
+        public WrapperMapElement[] exactWrappers = new WrapperMapElement[0];
+        public WrapperMapElement[] wildcardWrappers = new WrapperMapElement[0];
+        public WrapperMapElement[] extensionWrappers = new WrapperMapElement[0];
+        public int nesting = 0;
+
+        public String toString() {
+            return "ContextMapElement {" +
+            "name: \"" + name +
+            "\"\nnesting: \"" + nesting +
+            "\"\n}";
+        }
+    }
+
+
+    // ---------------------------------------------------- Wrapper Inner Class
+
+
+    public static class WrapperMapElement
+        extends MapElement {
+        public boolean jspWildCard = false;
+    }
+
+
+    public void destroy() {
+    }
+
+
+    public void doFilter(ServletRequest request, ServletResponse response,
+                         FilterChain chain) throws IOException,
+        ServletException {
+    }
+
+
+    public void init(FilterConfig filterConfig) throws ServletException {
+    }
+
+   
+}

Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/WebappServletMapper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/cli/Main.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/cli/Main.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/cli/Main.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/cli/Main.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.lite.cli;
+
+import org.apache.tomcat.integration.ObjectManager;
+import org.apache.tomcat.integration.jmx.JmxObjectManagerSpi;
+import org.apache.tomcat.integration.simple.SimpleObjectManager;
+import org.apache.tomcat.lite.TomcatLite;
+import org.apache.tomcat.lite.coyote.CoyoteHttp;
+
+/**
+ * Run tomcat lite, mostly for demo. In normal use you would
+ * embed it in an app, or use a small customized launcher.
+ * 
+ * With no arguments, it'll load only the root context / from 
+ * ./webapps/ROOT
+ *
+ * Most configuration can be done using web.xml files, few settings 
+ * can be set by flags. 
+ * 
+ * @author Costin Manolache
+ */
+public class Main {
+  
+  public static void main(String args[]) 
+          throws Exception {
+      
+      if (args.length == 0) {
+          System.err.println("Please specify at least one webapp.");
+          System.err.println("Example:");
+          System.err.println("-context /:webapps/ROOT -port 9999");
+      }
+
+      // Enable CLI processing
+      SimpleObjectManager.setArgs(args);
+      
+      TomcatLite lite = new TomcatLite();
+      ObjectManager om = lite.getObjectManager();
+
+      // add JMX support
+      new JmxObjectManagerSpi().register(om);
+      
+      lite.run();
+  }    
+}

Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/cli/Main.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/config.properties
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/config.properties?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/config.properties (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/config.properties Sat Apr  4 16:24:34 2009
@@ -0,0 +1,28 @@
+# Support for PropertiesSpi - the 'dummy' framework used for tomcat-lite
+# If tomcat is used with a proper framework, you need to bind and configure 
+# those objects in the framework. 
+
+# --- Class names for required plugin interfaces --- 
+
+org.apache.tomcat.lite.WebappServletMapper.(class)=org.apache.tomcat.lite.WebappServletMapper
+org.apache.tomcat.lite.WebappFilterMapper.(class)=org.apache.tomcat.lite.WebappFilterMapper
+
+# Sessions
+org.apache.tomcat.addons.UserSessionManager.(class)=org.apache.tomcat.servlets.session.SimpleSessionManager
+
+# *.jsp support
+org.apache.tomcat.addons.UserTemplateClassMapper.(class)=org.apache.tomcat.servlets.jsp.JasperCompilerTemplateClassMapper
+
+# Loader for web.xml - you can have your own custom class using a more efficient
+# or hardcoded.
+org.apache.tomcat.lite.ContextPreinitListener.(class)=org.apache.tomcat.lite.webxml.TomcatLiteWebXmlConfig
+
+# Connector class
+org.apache.tomcat.lite.Connector.(class)=org.apache.tomcat.lite.coyote.CoyoteHttp
+
+# --- Other required settings ---
+
+# Customize default and *.jsp mappings
+default-servlet.(class)=org.apache.tomcat.servlets.file.WebdavServlet
+jspwildcard-servlet.(class)=org.apache.tomcat.servlets.jsp.WildcardTemplateServlet
+

Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/config.properties
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/ClientAbortException.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/ClientAbortException.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/ClientAbortException.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/ClientAbortException.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.lite.coyote;
+
+import java.io.IOException;
+
+/**
+ * Wrap an IOException identifying it as being caused by an abort
+ * of a request by a remote client.
+ *
+ * @author Glenn L. Nielsen
+ * @version $Revision: 304063 $ $Date: 2005-08-18 06:25:18 -0700 (Thu, 18 Aug 2005) $
+ */
+
+public final class ClientAbortException extends IOException {
+
+
+    //------------------------------------------------------------ Constructors
+
+
+    /**
+     * Construct a new ClientAbortException with no other information.
+     */
+    public ClientAbortException() {
+
+        this(null, null);
+
+    }
+
+
+    /**
+     * Construct a new ClientAbortException for the specified message.
+     *
+     * @param message Message describing this exception
+     */
+    public ClientAbortException(String message) {
+
+        this(message, null);
+
+    }
+
+
+    /**
+     * Construct a new ClientAbortException for the specified throwable.
+     *
+     * @param throwable Throwable that caused this exception
+     */
+    public ClientAbortException(Throwable throwable) {
+
+        this(null, throwable);
+
+    }
+
+
+    /**
+     * Construct a new ClientAbortException for the specified message
+     * and throwable.
+     *
+     * @param message Message describing this exception
+     * @param throwable Throwable that caused this exception
+     */
+    public ClientAbortException(String message, Throwable throwable) {
+
+        super();
+        this.message = message;
+        this.throwable = throwable;
+
+    }
+
+
+    //------------------------------------------------------ Instance Variables
+
+
+    /**
+     * The error message passed to our constructor (if any)
+     */
+    protected String message = null;
+
+
+    /**
+     * The underlying exception or error passed to our constructor (if any)
+     */
+    protected Throwable throwable = null;
+
+
+    //---------------------------------------------------------- Public Methods
+
+
+    /**
+     * Returns the message associated with this exception, if any.
+     */
+    public String getMessage() {
+
+        return (message);
+
+    }
+
+
+    /**
+     * Returns the cause that caused this exception, if any.
+     */
+    public Throwable getCause() {
+        
+        return (throwable);
+        
+    }
+
+    
+    /**
+     * Return a formatted string that describes this exception.
+     */
+    public String toString() {
+
+        StringBuffer sb = new StringBuffer("ClientAbortException:  ");
+        if (message != null) {
+            sb.append(message);
+            if (throwable != null) {
+                sb.append(":  ");
+            }
+        }
+        if (throwable != null) {
+            sb.append(throwable.toString());
+        }
+        return (sb.toString());
+
+    }
+
+
+}

Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/ClientAbortException.java
------------------------------------------------------------------------------
    svn:eol-style = native



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