tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cos...@apache.org
Subject svn commit: r534293 [6/11] - in /tomcat/sandbox/tomcat-lite: ./ bin/ external/ java/ java/org/apache/commons/logging/ java/org/apache/tomcat/lite/ java/org/apache/tomcat/lite/ctxmap/ java/org/apache/tomcat/lite/http/ java/org/apache/tomcat/lite/http11/...
Date Wed, 02 May 2007 02:22:50 GMT
Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/config/WebXml.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/config/WebXml.java?view=auto&rev=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/config/WebXml.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/config/WebXml.java Tue May  1 19:22:45 2007
@@ -0,0 +1,362 @@
+/*
+ */
+package org.apache.tomcat.servlets.config;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import javax.servlet.ServletException;
+
+import org.apache.tomcat.util.DomUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/** Process an web.xml file
+ * 
+ * @author costin
+ */
+public class WebXml {
+    WebAppData d = new WebAppData();
+    
+    public WebXml() {
+    }
+
+    public void saveWebAppData(String fileName) throws IOException {
+        ObjectOutputStream oos = 
+            new ObjectOutputStream(new FileOutputStream(fileName));
+        oos.writeObject(d);
+        oos.close();
+    }
+    
+    public WebAppData getWebAppData() {
+        return d;
+    }
+    
+    public void readWebXml(String baseDir) throws ServletException {
+        try {
+            File webXmlFile = new File( baseDir + "/WEB-INF/web.xml");
+            if (!webXmlFile.exists()) {
+                return;
+            }
+            d.fileName = webXmlFile.getCanonicalPath();
+            d.timestamp = webXmlFile.lastModified();
+            
+            FileInputStream fileInputStream = new FileInputStream(webXmlFile);
+            readWebXml(fileInputStream);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new ServletException(e);
+        }
+    }
+    
+     public void readWebXml(InputStream fileInputStream) throws ServletException {
+         try {
+                    
+            Document document = DomUtil.readXml(fileInputStream);
+            Node webappNode = DomUtil.getChild(document, "web-app");
+
+            String fullS = DomUtil.getAttribute(webappNode, "full");
+            if (fullS != null && fullS.equalsIgnoreCase("true")) {
+                d.full = true;
+            }
+            // Process each child of web-app
+            Node confNode = DomUtil.getChild(webappNode, "filter");
+            while (confNode != null ) {
+                processFilter(confNode);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "filter-mapping");
+            while (confNode != null ) {
+                processFilterMapping(confNode);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "context-param");
+            while (confNode != null ) {
+                String n = DomUtil.getChildContent(confNode, "param-name").trim();
+                String v = DomUtil.getChildContent(confNode, "param-value").trim();
+                d.contextParam.put(n, v);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "mime-mapping");
+            while (confNode != null ) {
+                String n = DomUtil.getChildContent(confNode, "extension");
+                String t = DomUtil.getChildContent(confNode, "mime-type");
+                d.mimeMapping.put(n, t);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "error-page");
+            while (confNode != null ) {
+                processErrorPage(confNode);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "jsp-config");
+            while (confNode != null ) {
+                processJspConfig(confNode);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "servlet");
+            while (confNode != null ) {
+                processServlet(confNode);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "servlet-mapping");
+            while (confNode != null ) {
+                processServletMapping(confNode);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "listener");
+            while (confNode != null ) {
+                String lClass = DomUtil.getChildContent(confNode, "listener-class");
+                d.listenerClass.add(lClass);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "security-constraint");
+            while (confNode != null ) {
+                processSecurityConstraint(confNode);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "login-config");
+            while (confNode != null ) {
+                processLoginConfig(confNode);
+                confNode = DomUtil.getNext(confNode);
+                if (confNode != null) 
+                    throw new ServletException("Multiple login-config");
+            }
+
+            confNode = DomUtil.getChild(webappNode, "session-config");
+            while (confNode != null ) {
+                String n = DomUtil.getChildContent(confNode, "session-timeout");
+                int stout = Integer.parseInt(n);
+                d.sessionTimeout = stout;
+                confNode = DomUtil.getNext(confNode);
+                if (confNode != null) 
+                    throw new ServletException("Multiple session-config");
+            }
+
+            confNode = DomUtil.getChild(webappNode, "welcome-file-list");
+            while (confNode != null ) {
+                Node wf = DomUtil.getChild(confNode, "welcome-file");
+                while (wf != null) {
+                    String file = DomUtil.getContent(wf);
+                    d.welcomeFileList.add(file);
+                    wf = DomUtil.getNext(wf);
+                }
+                // more sections ?
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            // Not supported right now - TODO: collect, have jndi plugin
+            confNode = DomUtil.getChild(webappNode, "env-entry");
+            while (confNode != null ) {
+                processEnvEntry(confNode);
+                confNode = DomUtil.getNext(confNode);
+            }
+            
+            confNode = DomUtil.getChild(webappNode, "locale-encoding-mapping-list");
+            while (confNode != null ) {
+                confNode = DomUtil.getNext(confNode);
+                String n = DomUtil.getChildContent(confNode, "locale");
+                String t = DomUtil.getChildContent(confNode, "encoding");
+                d.localeEncodingMapping.put(n, t);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "distributable");
+            while (confNode != null ) {
+                d.distributable = true;
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(confNode, "security-role");
+            while (confNode != null ) {
+                String n = DomUtil.getChildContent(confNode, "role-name");
+                d.securityRole.add(n);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    throw new ServletException(e);
+                }
+    }
+    
+    private void processJspConfig(Node confNode) {
+        Node tagLib = DomUtil.getChild(confNode, "taglib");
+        while (tagLib != null) {
+            String uri = DomUtil.getChildContent(tagLib, "taglib-uri");
+            String l = DomUtil.getChildContent(tagLib, "taglib-location");
+            //d.tagLibs.put(uri, l);
+            tagLib = DomUtil.getNext(tagLib);
+        }
+        
+        tagLib = DomUtil.getChild(confNode, "jsp-property-group");
+        while (tagLib != null) {
+            // That would be the job of the JSP servlet to process.
+            tagLib = DomUtil.getNext(tagLib);
+        }
+    }
+
+    private void processEnvEntry(Node confNode) {
+        EnvEntryData ed = new EnvEntryData();
+        ed.envEntryName = DomUtil.getChildContent(confNode,"env-entry-name");
+        ed.envEntryType = DomUtil.getChildContent(confNode,"env-entry-type");
+        ed.envEntryValue = DomUtil.getChildContent(confNode,"env-entry-value");
+        d.envEntry.add(ed);
+    }
+
+    private void processLoginConfig(Node confNode) {
+        d.authMethod = DomUtil.getChildContent(confNode,"auth-method");
+        d.realmName = DomUtil.getChildContent(confNode,"auth-method");
+        Node formNode = DomUtil.getChild(confNode, "form-login-config");
+        if (formNode != null) {
+            d.formLoginPage = DomUtil.getChildContent(formNode,"form-login-page");
+            d.formErrorPage = DomUtil.getChildContent(formNode,"form-error-page");
+        }
+    }
+
+    private void processSecurityConstraint(Node confNode) {
+        SecurityConstraintData sd = new SecurityConstraintData();
+        Node cn = DomUtil.getChild(confNode, "web-resource-collection");
+        while (cn != null) {
+            WebResourceCollectionData wrd = new WebResourceCollectionData();
+            wrd.webResourceName = DomUtil.getChildContent(cn, "web-resource-name");
+            Node scn = DomUtil.getChild(cn,"url-pattern");
+            while (scn != null) {
+                wrd.urlPattern.add(DomUtil.getContent(scn));
+                scn = DomUtil.getNext(scn);
+            }
+            scn = DomUtil.getChild(cn,"http-method");
+            while (scn != null) {
+                wrd.httpMethod.add(DomUtil.getContent(scn));
+                scn = DomUtil.getNext(scn);
+            }
+            cn = DomUtil.getNext(cn);
+        }
+        d.securityConstraint.add(sd);
+    }
+
+    private void processErrorPage(Node confNode) {
+        String name = DomUtil.getChildContent(confNode,"location");
+        String c = DomUtil.getChildContent(confNode,"error-code");
+        String t = DomUtil.getChildContent(confNode,"exception-type");
+        if (c != null) {
+            d.errorPageCode.put(c, name);
+        }
+        if (t != null) {
+            d.errorPageException.put(t, name);
+        }
+    }
+
+    private void processServlet(Node confNode) throws ServletException {
+        ServletData sd = new ServletData();
+
+        sd.servletName = DomUtil.getChildContent(confNode,"servlet-name");
+        sd.servletClass = DomUtil.getChildContent(confNode,"servlet-class");
+        sd.jspFile = DomUtil.getChildContent(confNode,"jsp-file");
+        
+        processInitParams(confNode, sd.initParams);
+        
+        d.servlets.put( sd.servletName, sd );
+        
+        String los = DomUtil.getChildContent(confNode, "load-on-startup");
+        if (los != null ) { 
+            sd.loadOnStartup = Integer.parseInt(los);
+        }
+        
+        Node sn = DomUtil.getChild(confNode, "security-role-ref");
+        while (sn != null ) {
+            String roleName = DomUtil.getChildContent(sn, "role-name");
+            String roleLink = DomUtil.getChildContent(sn, "role-link");
+            if (roleLink == null) {
+                sd.securityRoleRef.put(roleName, "");
+            } else {
+                sd.securityRoleRef.put(roleName, roleLink);
+            }
+            sn = DomUtil.getNext(sn);
+        }
+    }
+
+    private void processInitParams(Node confNode, HashMap initParams) {
+        Node initN = DomUtil.getChild(confNode, "init-param");
+        while (initN != null ) {
+            String n = DomUtil.getChildContent(initN, "param-name");
+            String v = DomUtil.getChildContent(initN, "param-value");
+            initParams.put(n, v);
+            initN = DomUtil.getNext(initN);
+        }
+    }
+
+    private void processServletMapping(Node confNode) {
+        String name = DomUtil.getChildContent(confNode,"servlet-name");
+        String path = DomUtil.getChildContent(confNode,"url-pattern").trim();
+        
+        if (! (path.startsWith("/") || path.startsWith("*"))) {
+            // backward compat 
+            path = "/" + path;
+        }
+        d.servletMapping.put(path, name);
+    }
+
+    private void processFilterMapping(Node confNode) {
+      String filterName = DomUtil.getChildContent(confNode,"filter-name");
+      // multiple 
+      ArrayList dispatchers = new ArrayList();
+      Node dataN = DomUtil.getChild(confNode, "dispatcher");
+      while (dataN != null ) {
+          String d = DomUtil.getContent(dataN);
+          dispatchers.add(d);
+          dataN = DomUtil.getNext(dataN);
+      }
+      
+      // Multiple url-pattern and servlet-name in one
+      // mapping rule. Need to be applied in order.
+      dataN = DomUtil.getChild(confNode, "url-pattern");
+      while (dataN != null ) {
+        FilterMappingData fm = new FilterMappingData();
+        fm.filterName = filterName;
+        fm.dispatcher = dispatchers;
+        String path = DomUtil.getContent(dataN);
+        dataN = DomUtil.getNext(dataN);
+        fm.urlPattern = path;
+        d.filterMappings.add(fm);
+      }
+      dataN = DomUtil.getChild(confNode, "servlet-name");
+      while (dataN != null ) {
+        FilterMappingData fm = new FilterMappingData();
+        fm.filterName = filterName;
+        fm.dispatcher = dispatchers;
+        String sn = DomUtil.getContent(dataN);
+        dataN = DomUtil.getNext(dataN);
+        fm.servletName = sn;
+        d.filterMappings.add(fm);
+      }
+    }
+
+    private void processFilter(Node confNode) {
+        String name = DomUtil.getChildContent(confNode,"filter-name");
+        String sclass = DomUtil.getChildContent(confNode,"filter-class");
+        
+        FilterData fd = new FilterData();
+        processInitParams(confNode, fd.initParams);
+        fd.filterName = name;
+        fd.filterClass = sclass;
+        d.filters.put(name, fd);
+    }
+    
+}

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/deploy/InitServlet.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/deploy/InitServlet.java?view=diff&rev=534293&r1=534292&r2=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/deploy/InitServlet.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/deploy/InitServlet.java Tue May  1 19:22:45 2007
@@ -1,30 +1,113 @@
 package org.apache.tomcat.servlets.deploy;
 
 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.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.tomcat.lite.ServletContextImpl;
 import org.apache.tomcat.lite.TomcatLite;
-import org.apache.tomcat.lite.TomcatLite.ContextConfigData;
-import org.apache.tomcat.lite.TomcatLite.EngineData;
+import org.apache.tomcat.servlets.config.WebAppData;
 
+/**
+ *  Called on startup, if /__x_deploy app is present. Will generate or refresh
+ *  the .ser config file.
+ * 
+ * @author Costin Manolache
+ */
 public class InitServlet extends HttpServlet {
 
-    @Override
+    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();
+    }
+
+    /** 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
+        public String path; // path where it is mapped. ( for multiple - use mapper,
+          // it is not allowed by spec )
+        
+        public WebAppData webXml;
+    }
+
     protected void service(HttpServletRequest req, HttpServletResponse resp)
         throws ServletException, IOException
     {
-        EngineData ed = initConfig();
-        req.setAttribute("engineData", ed);
+        // TODO: more requests, deploy, status, etc
+        initConfig();
     }
     
+    public boolean checkConfig(TomcatLite tomcat, InitServlet.EngineData engineData) {
+        // TODO: validate, check timestamps of all recorded objects
+        if (engineData.contexts.size() == 0 ) {
+            return false;
+        }
+        Iterator i1 = engineData.contexts.iterator();
+        while (i1.hasNext()) {
+            InitServlet.ContextConfigData x = (InitServlet.ContextConfigData) i1.next();
+            if (x.webXml != null) {
+                long ts = x.webXml.timestamp;
+                String file = x.webXml.fileName;
+                if (file != null) {
+                    File f = new File(file);
+                    if (! f.exists()) {
+                        System.err.println("Missing context " + file);
+                        return false;
+                    } else if (f.lastModified() > ts) {
+                        System.err.println("File is newer " + file);
+                        return false;
+                    } 
+                }
+            } else {
+                // maybe we should check for a new file ? 
+            }
+        }
+        
+        //        tomcat.setEngineData(ed);
+
+        return true;
+    }
+    
+    public void saveEngineData(InitServlet.EngineData ed)
+        throws FileNotFoundException, IOException
+    {
+        File work = TomcatLite.getServletImpl().getWork();
+        if (!work.exists()) {
+            work.mkdirs();
+        }
+        FileOutputStream fos = new FileOutputStream(new File(work, 
+            "tomcatLite.ser"));
+        ObjectOutputStream oos = new ObjectOutputStream(fos);
+        oos.writeObject(ed);
+        oos.close();
+    }
+
+    
+    
     /** Read a config file or directory layouts, generate the EngineData config
      * info object. 
      * 
@@ -42,36 +125,134 @@
      *  - static set of settings ( hardcoded )
      * 
      * @return
+     * @throws ServletException 
      */
-    public EngineData initConfig() {
-        EngineData ed = new TomcatLite.EngineData();
+    public InitServlet.EngineData initConfig() throws ServletException {
+        TomcatLite tomcat = 
+            (TomcatLite) getServletContext().getAttribute(TomcatLite.A_ENGINE);
         
-        File webappD = new File("webapps");
-        if (!webappD.exists()) {
-            return ed;
-        }
-        File[] dirs = webappD.listFiles();
-        for (File dir: dirs) {
-            if (dir.isDirectory()) {
-                String path = dir.getName();
-                // TODO: demangling, etc
-                if ("ROOT".equals(path)) { 
-                    path = "/";
-                } else {
-                    path = "/" + path;
-                }
-                ed.contexts.add(new ContextConfigData(dir.getAbsolutePath(), 
-                                                      path)); 
+
+        InitServlet.EngineData ed = null;
+        File initFile = new File(tomcat.getWork(), "tomcatLite.ser");
+        if (initFile.exists()) {
+            try {
+                ObjectInputStream ois = 
+                    new ObjectInputStream(new FileInputStream(initFile));
+                ed = (InitServlet.EngineData)ois.readObject();
+            } catch(IOException ex) {
+                ed = null;
+            } catch (ClassNotFoundException e) {
+                ed = null;
+            }
+        }
+        // assert: tomcatLite.ser has at least the engineCtx.
+        
+        if (ed != null) {
+            // check for updates
+            boolean valid = checkConfig(tomcat, ed);
+            if (valid) {
+                processData(tomcat, ed);
+                return ed;
+            } else {
+                ed = null;
             }
         }
         
+        ed = new InitServlet.EngineData();
+        
+        File f = new File(tomcat.getRoot(), "WEB-INF");
+        if (f.exists() && new File(f, "web.xml").exists()) {
+            
+            System.err.println("Single-app mode " + f);
+
+            String base = tomcat.getRoot().getAbsolutePath();
+            ed.contexts.add(new InitServlet.ContextConfigData(base, 
+                "/")); 
+            
+        } else {
+            File webappD = new File(tomcat.getRoot(), "webapps");
+            if (webappD.exists()) {
+                File[] dirs = webappD.listFiles();
+                for (int i = 0; i < dirs.length; i++) {
+                    File dir =  dirs[i];
+                    if (dir.isDirectory()) {
+                        String path = dir.getName();
+                        // TODO: demangling, etc
+                        if ("ROOT".equals(path)) { 
+                            path = "/";
+                        } else {
+                            path = "/" + path;
+                        }
+                        ed.contexts.add(new InitServlet.ContextConfigData(dir.getAbsolutePath(), 
+                                path)); 
+                    }
+                }
+            } 
+            System.err.println("Loading configs " + webappD.getAbsolutePath() + 
+                    " " + ed.contexts.size() + " " + ed.contexts);
+            
+        }
+
+        processData(tomcat, ed);
+
+
+        try {
+            saveEngineData(ed);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
         return ed;
     }
-    
-    public static void main(String args[]) throws IOException {
+
+    private void processData(TomcatLite tomcat, InitServlet.EngineData ed) throws ServletException {
+        // Just load the config for all contexts in config
+        Iterator ctxI = ed.contexts.iterator();
+        WebappContextMapper hostMapper = null;
+        
+        while (ctxI.hasNext()) {
+            InitServlet.ContextConfigData ctxD = (InitServlet.ContextConfigData) ctxI.next();
+            System.err.println("Loading context: " + ctxD.path + " " + 
+                    ctxD.basePath);
+            ServletContextImpl ctx = 
+                (ServletContextImpl)tomcat.addServletContext(null, 
+                                                      ctxD.basePath, 
+                                                      ctxD.path);
+            if (hostMapper == null) {
+                hostMapper = new WebappContextMapper();
+            }
+            hostMapper.addContext(null, ctx, TomcatLite.DEFAULT_WELCOME,
+                    new File(ctx.getBasePath()));
+
+
+            
+            if (ctxD.webXml != null) {
+                ctx.processWebAppData(ctxD.webXml);
+            }
+            
+            ctx.init();
+            
+            if (ctxD.webXml == null) {
+                ctxD.webXml = ctx.getConfig();
+            }
+        }
+        
+        if (hostMapper != null) {
+            tomcat.setContextMapper(hostMapper);
+        }
+    }
+
+    /** Offline - generate the .ser config file
+     * 
+     * @param args
+     * @throws IOException
+     * @throws ServletException 
+     */
+    public static void main(String args[]) throws IOException, ServletException {
         InitServlet is = new InitServlet();
-        EngineData ed = is.initConfig();
-        TomcatLite.getServletImpl().saveEngineData(ed);
+        InitServlet.EngineData ed = is.initConfig();
+        is.saveEngineData(ed);
     }
 
 }

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/deploy/WebAnnotation.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/deploy/WebAnnotation.java?view=diff&rev=534293&r1=534292&r2=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/deploy/WebAnnotation.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/deploy/WebAnnotation.java Tue May  1 19:22:45 2007
@@ -1,5 +1,6 @@
 package org.apache.tomcat.servlets.deploy;
 
+import java.util.Iterator;
 import java.util.List;
 
 import javax.annotation.security.DeclareRoles;
@@ -57,7 +58,9 @@
      * Process the annotations for the filters.
      */
     static void loadApplicationFilterAnnotations(WebAppData context, ClassLoader classLoader) {
-        for(FilterData fc: context.filters.values()) {
+        Iterator i1 = context.filters.values().iterator();
+        while (i1.hasNext()) {
+            FilterData fc = (FilterData) i1.next();
             loadClassAnnotation(context, fc.filterClass, classLoader);
         }
     }
@@ -70,7 +73,10 @@
     static void loadApplicationServletAnnotations(WebAppData context, ClassLoader classLoader) {
         Class classClass = null;
         
-        for (ServletData sd: context.servlets.values()) {
+        
+        Iterator i1 = context.servlets.values().iterator();
+        while (i1.hasNext()) {
+            ServletData sd = (ServletData) i1.next();
             if (sd.servletClass == null) {
                 continue;
             }

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/deploy/WebappContextMapper.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/deploy/WebappContextMapper.java?view=auto&rev=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/deploy/WebappContextMapper.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/deploy/WebappContextMapper.java Tue May  1 19:22:45 2007
@@ -0,0 +1,329 @@
+package org.apache.tomcat.servlets.deploy;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.ArrayList;
+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 javax.servlet.http.HttpServletRequest;
+
+import org.apache.tomcat.lite.ServletContextImpl;
+import org.apache.tomcat.lite.ServletRequestImpl;
+import org.apache.tomcat.lite.WebappServletMapper;
+import org.apache.tomcat.lite.WebappServletMapper.ContextMapElement;
+import org.apache.tomcat.lite.util.MappingData;
+import org.apache.tomcat.util.buf.CharChunk;
+import org.apache.tomcat.util.buf.MessageBytes;
+
+/** 
+ * This handles host and context mapping.
+ * 
+ * All context-specific mapping is done in WebappFilerMapper and 
+ * WebappServletMapper.
+ * 
+ * You can extend and override the mapper in MapperAdapter.
+ */
+public class WebappContextMapper implements Filter {
+    
+    /** Data we store for each host 
+     */
+    static class HostMappingInfo
+    {
+       public WebappContextMapper.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();
+       }
+
+   }
+
+    public static class HostData implements Serializable {
+        /** Must be lowercase */
+        public String hostName;
+        public ArrayList/*<String>*/ aliases = new ArrayList();
+    }
+
+    /** 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 WebappContextMapper.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 IOException, ServletException {
+        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 {
+        ServletRequestImpl req = (ServletRequestImpl)request;
+        mapContext(req);
+    }
+    
+    public void destroy() {
+    }
+    
+    public ServletContextImpl getContext(ServletContextImpl impl, String uri) {
+        HostMappingInfo host = (HostMappingInfo) contextsParents.get(impl);
+        if (host == null) host = defaultHost;
+        return getContext(host, uri);
+    }
+    
+    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/servlets/file/CopyUtils.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/CopyUtils.java?view=auto&rev=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/CopyUtils.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/CopyUtils.java Tue May  1 19:22:45 2007
@@ -0,0 +1,257 @@
+package org.apache.tomcat.servlets.file;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.Reader;
+
+import javax.servlet.ServletOutputStream;
+
+public class CopyUtils {
+    protected static int input = 2048;
+
+    /**
+     * Copy the contents of the specified input stream to the specified
+     * output stream, and ensure that both streams are closed before returning
+     * (even in the face of an exception).
+     *
+     * @param resourceInfo The resource info
+     * @param writer The writer to write to
+     *
+     * @exception IOException if an input/output error occurs
+     */
+    public static void copy(InputStream is, 
+                            PrintWriter writer,
+                            String fileEncoding)
+        throws IOException {
+
+        IOException exception = null;
+
+        InputStream resourceInputStream = is;
+
+        Reader reader;
+        if (fileEncoding == null) {
+            reader = new InputStreamReader(resourceInputStream);
+        } else {
+            reader = new InputStreamReader(resourceInputStream,
+                                           fileEncoding);
+        }
+
+        // Copy the input stream to the output stream
+        exception = copyRange(reader, writer);
+
+        // Clean up the reader
+        try {
+            reader.close();
+        } catch (Throwable t) {
+            ;
+        }
+
+        // Rethrow any exception that has occurred
+        if (exception != null)
+            throw exception;
+
+    }
+
+    /**
+     * Copy the contents of the specified input stream to the specified
+     * output stream, and ensure that both streams are closed before returning
+     * (even in the face of an exception).
+     *
+     * @param resourceInfo The resource information
+     * @param ostream The output stream to write to
+     *
+     * @exception IOException if an input/output error occurs
+     */
+    public static void copy(InputStream is, OutputStream ostream)
+            throws IOException {
+
+        IOException exception = null;
+        InputStream resourceInputStream = null;
+
+        resourceInputStream = is;
+
+        InputStream istream = new BufferedInputStream
+            (resourceInputStream, input);
+
+        // Copy the input stream to the output stream
+        exception = CopyUtils.copyRange(istream, ostream);
+
+        // Clean up the input stream
+        try {
+            istream.close();
+        } catch (Throwable t) {
+            ;
+        }
+
+        // Rethrow any exception that has occurred
+        if (exception != null)
+            throw exception;
+    }
+
+    /**
+     * Copy the contents of the specified input stream to the specified
+     * output stream, and ensure that both streams are closed before returning
+     * (even in the face of an exception).
+     *
+     * @param istream The input stream to read from
+     * @param ostream The output stream to write to
+     * @return Exception which occurred during processing
+     */
+    public static IOException copyRange(InputStream istream,
+                                        OutputStream ostream) {
+
+        // Copy the input stream to the output stream
+        IOException exception = null;
+        byte buffer[] = new byte[input];
+        int len = buffer.length;
+        while (true) {
+            try {
+                len = istream.read(buffer);
+                if (len == -1)
+                    break;
+                ostream.write(buffer, 0, len);
+            } catch (IOException e) {
+                exception = e;
+                len = -1;
+                break;
+            }
+        }
+        return exception;
+
+    }
+
+
+    /**
+     * Copy the contents of the specified input stream to the specified
+     * output stream, and ensure that both streams are closed before returning
+     * (even in the face of an exception).
+     *
+     * @param reader The reader to read from
+     * @param writer The writer to write to
+     * @return Exception which occurred during processing
+     */
+    public static IOException copyRange(Reader reader, PrintWriter writer) {
+
+        // Copy the input stream to the output stream
+        IOException exception = null;
+        char buffer[] = new char[input];
+        int len = buffer.length;
+        while (true) {
+            try {
+                len = reader.read(buffer);
+                if (len == -1)
+                    break;
+                writer.write(buffer, 0, len);
+            } catch (IOException e) {
+                exception = e;
+                len = -1;
+                break;
+            }
+        }
+        return exception;
+
+    }
+
+
+    /**
+     * Copy the contents of the specified input stream to the specified
+     * output stream, and ensure that both streams are closed before returning
+     * (even in the face of an exception).
+     *
+     * @param istream The input stream to read from
+     * @param ostream The output stream to write to
+     * @param start Start of the range which will be copied
+     * @param end End of the range which will be copied
+     * @return Exception which occurred during processing
+     */
+    public static IOException copyRange(InputStream istream,
+                                  ServletOutputStream ostream,
+                                  long start, long end) {
+
+        try {
+            istream.skip(start);
+        } catch (IOException e) {
+            return e;
+        }
+
+        IOException exception = null;
+        long bytesToRead = end - start + 1;
+
+        byte buffer[] = new byte[input];
+        int len = buffer.length;
+        while ( (bytesToRead > 0) && (len >= buffer.length)) {
+            try {
+                len = istream.read(buffer);
+                if (bytesToRead >= len) {
+                    ostream.write(buffer, 0, len);
+                    bytesToRead -= len;
+                } else {
+                    ostream.write(buffer, 0, (int) bytesToRead);
+                    bytesToRead = 0;
+                }
+            } catch (IOException e) {
+                exception = e;
+                len = -1;
+            }
+            if (len < buffer.length)
+                break;
+        }
+
+        return exception;
+
+    }
+
+
+
+    /**
+     * Copy the contents of the specified input stream to the specified
+     * output stream, and ensure that both streams are closed before returning
+     * (even in the face of an exception).
+     *
+     * @param reader The reader to read from
+     * @param writer The writer to write to
+     * @param start Start of the range which will be copied
+     * @param end End of the range which will be copied
+     * @return Exception which occurred during processing
+     */
+    public static IOException copyRange(Reader reader, PrintWriter writer,
+                                  long start, long end) {
+
+        try {
+            reader.skip(start);
+        } catch (IOException e) {
+            return e;
+        }
+
+        IOException exception = null;
+        long bytesToRead = end - start + 1;
+
+        char buffer[] = new char[input];
+        int len = buffer.length;
+        while ( (bytesToRead > 0) && (len >= buffer.length)) {
+            try {
+                len = reader.read(buffer);
+                if (bytesToRead >= len) {
+                    writer.write(buffer, 0, len);
+                    bytesToRead -= len;
+                } else {
+                    writer.write(buffer, 0, (int) bytesToRead);
+                    bytesToRead = 0;
+                }
+            } catch (IOException e) {
+                exception = e;
+                len = -1;
+            }
+            if (len < buffer.length)
+                break;
+        }
+
+        return exception;
+
+    }
+
+}

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/DefaultServlet.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/DefaultServlet.java?view=diff&rev=534293&r1=534292&r2=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/DefaultServlet.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/DefaultServlet.java Tue May  1 19:22:45 2007
@@ -20,19 +20,13 @@
 
 import java.io.BufferedInputStream;
 import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.io.Reader;
-import java.io.StringWriter;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Date;
@@ -48,10 +42,7 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.tomcat.servlets.util.CopyUtils;
-import org.apache.tomcat.servlets.util.FileCopyUtils;
-import org.apache.tomcat.servlets.util.Range;
-import org.apache.tomcat.servlets.util.URLEncoder;
+import org.apache.tomcat.util.http.Range;
 import org.apache.tomcat.util.res.StringManager;
 
 /**
@@ -413,7 +404,8 @@
                                    request.getRequestURI());
                 return;
             }
-            dir2Html.renderDir(request, response, resFile, fileEncoding, content );
+            dir2Html.renderDir(request, response, resFile, fileEncoding, content,
+                    path);
             
             return;
         }

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/Dir2Html.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/Dir2Html.java?view=diff&rev=534293&r1=534292&r2=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/Dir2Html.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/Dir2Html.java Tue May  1 19:22:45 2007
@@ -48,8 +48,6 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.tomcat.servlets.util.CopyUtils;
-import org.apache.tomcat.servlets.util.URLEncoder;
 import org.apache.tomcat.util.res.StringManager;
 
 /**
@@ -156,7 +154,7 @@
         throws IOException, ServletException {
 
         // Serve the requested resource, including the data content
-        serveResource(request, response, true);
+        //serveResource(request, response, true);
 
     }
 
@@ -166,7 +164,7 @@
         throws IOException, ServletException {
 
         // Serve the requested resource, without the data content
-        serveResource(request, response, false);
+        //serveResource(request, response, false);
 
     }
 
@@ -193,7 +191,8 @@
      */
     protected void serveResource(HttpServletRequest request,
                                  HttpServletResponse response,
-                                 boolean content)
+                                 boolean content, 
+                                 String relativePath)
         throws IOException, ServletException {
 
         // Identify the requested resource path - checks include attributes
@@ -211,7 +210,8 @@
         boolean isDir = resFile.isDirectory();
         
         if (isDir) {
-            renderDir(request, response, resFile,"UTF=8", content );
+            renderDir(request, response, resFile,"UTF=8", content,
+                    relativePath);
             return;
         }
         
@@ -227,7 +227,8 @@
             HttpServletResponse response, 
             File resFile,
             String fileEncoding,
-            boolean content) throws IOException {
+            boolean content,
+            String relativePath) throws IOException {
         
         String contentType = "text/html;charset=" + fileEncoding;
 
@@ -259,7 +260,7 @@
         if (content) {
             // Serve the directory browser
             renderResult =
-                render(request.getContextPath(), resFile);
+                render(request.getContextPath(), resFile, relativePath);
         }
 
 
@@ -295,8 +296,9 @@
     /**
      *  Decide which way to render. HTML or XML.
      */
-    protected InputStream render(String contextPath, File cacheEntry) {
-        return renderHtml(contextPath, cacheEntry);
+    protected InputStream render(String contextPath, File cacheEntry,
+                                 String relativePath) {
+        return renderHtml(contextPath, cacheEntry, relativePath);
     }
 
 
@@ -307,16 +309,17 @@
      * @param contextPath Context path to which our internal paths are
      *  relative
      */
-    protected InputStream renderHtml(String contextPath, File cacheEntry) {
+    protected InputStream renderHtml(String contextPath, File cacheEntry,
+                                     String relativePath) {
 
-        String name = cacheEntry.getName();
+        String dirName = cacheEntry.getName();
 
         // Number of characters to trim from the beginnings of filenames
-        int trim = name.length();
-        if (!name.endsWith("/"))
-            trim += 1;
-        if (name.equals("/"))
-            trim = 1;
+//        int trim = relativePath.length();
+//        if (!relativePath.endsWith("/"))
+//            trim += 1;
+//        if (relativePAth.equals("/"))
+//            trim = 1;
 
         // Prepare a writer to a buffered area
         ByteArrayOutputStream stream = new ByteArrayOutputStream();
@@ -338,7 +341,7 @@
         sb.append("<html>\r\n");
         sb.append("<head>\r\n");
         sb.append("<title>");
-        sb.append(sm.getString("directory.title", name));
+        sb.append(sm.getString("directory.title", dirName));
         sb.append("</title>\r\n");
         sb.append("<STYLE><!--");
         sb.append(TOMCAT_CSS);
@@ -346,34 +349,12 @@
         sb.append("</head>\r\n");
         sb.append("<body>");
         sb.append("<h1>");
-        sb.append(sm.getString("directory.title", name));
-
-        // Render the link to our parent (if required)
-        String parentDirectory = name;
-        if (parentDirectory.endsWith("/")) {
-            parentDirectory =
-                parentDirectory.substring(0, parentDirectory.length() - 1);
-        }
-        int slash = parentDirectory.lastIndexOf('/');
-        if (slash >= 0) {
-            String parent = name.substring(0, slash);
-            sb.append(" - <a href=\"");
-            sb.append(rewrittenContextPath);
-            if (parent.equals(""))
-                parent = "/";
-            sb.append(rewriteUrl(parent));
-            if (!parent.endsWith("/"))
-                sb.append("/");
-            sb.append("\">");
-            sb.append("<b>");
-            sb.append(sm.getString("directory.parent", parent));
-            sb.append("</b>");
-            sb.append("</a>");
-        }
-
+        sb.append(sm.getString("directory.title", dirName));
         sb.append("</h1>");
+
         sb.append("<HR size=\"1\" noshade=\"noshade\">");
 
+
         sb.append("<table width=\"100%\" cellspacing=\"0\"" +
                      " cellpadding=\"5\" align=\"center\">\r\n");
 
@@ -389,11 +370,35 @@
         sb.append(sm.getString("directory.lastModified"));
         sb.append("</strong></font></td>\r\n");
         sb.append("</tr>");
+        boolean shade = false;
+
+        // Render the link to our parent (if required)
+        String parentDirectory = relativePath;
+        if (parentDirectory.endsWith("/")) {
+            parentDirectory =
+                parentDirectory.substring(0, parentDirectory.length() - 1);
+        }
+        int slash = parentDirectory.lastIndexOf('/');
+        if (slash >= 0) {
+            String parent = relativePath.substring(0, slash);
+            sb.append("<tr>\r\n<td align=\"left\">&nbsp;&nbsp;\r\n<a href=\"..");
+//            sb.append(rewrittenContextPath);
+//            if (parent.equals(""))
+//               parent = "/";
+//            sb.append(rewriteUrl(parent));
+//            if (!parent.endsWith("/"))
+//                sb.append("/");
+            sb.append("\">");
+            //sb.append("<b>");
+            sb.append("..");
+            //sb.append("</b>");
+            sb.append("</a></td></tr>");
+            shade = true;
+        }
 
 
         // Render the directory entries within this directory
         String[] files = cacheEntry.list();
-        boolean shade = false;
         for (int i=0; i<files.length; i++) {
 
             String resourceName = files[i];
@@ -412,8 +417,17 @@
 
             sb.append("<td align=\"left\">&nbsp;&nbsp;\r\n");
             sb.append("<a href=\"");
-            sb.append(rewrittenContextPath);
-            //resourceName = rewriteUrl(name + "/" + resourceName);
+            if (! relativePath.endsWith("/")) {
+                sb.append(dirName + "/");
+            }
+            //sb.append(rewrittenContextPath);
+//            if (! rewrittenContextPath.endsWith("/")) {
+//                sb.append("/");
+//            }
+//            if ( ! relativePath.equals("")) {
+//                String link = rewriteUrl(relativePath);
+//                sb.append(link).append("/");
+//            }
             sb.append(resourceName);
             boolean isDir = childCacheEntry.isDirectory(); 
             if (isDir)

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/FileCopyUtils.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/FileCopyUtils.java?view=auto&rev=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/FileCopyUtils.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/FileCopyUtils.java Tue May  1 19:22:45 2007
@@ -0,0 +1,112 @@
+package org.apache.tomcat.servlets.file;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.Reader;
+
+import javax.servlet.ServletOutputStream;
+
+import org.apache.tomcat.util.http.Range;
+
+
+/** Like CopyUtils, but with File as source.
+ *  
+ *  This has the potential to be optimized with JNI
+ */
+public class FileCopyUtils {
+    protected static int input = 2048;
+
+    public static void copy(File f, OutputStream ostream)
+            throws IOException {
+        CopyUtils.copy(new FileInputStream(f), ostream);
+    }
+
+
+    public static void copy(File cacheEntry, 
+                            PrintWriter writer,
+                            String fileEncoding)
+            throws IOException {
+        CopyUtils.copy(new FileInputStream(cacheEntry), writer, fileEncoding);
+    }
+
+    /**
+     * Copy the contents of the specified input stream to the specified
+     * output stream, and ensure that both streams are closed before returning
+     * (even in the face of an exception).
+     *
+     * @param resourceInfo The ResourceInfo object
+     * @param ostream The output stream to write to
+     * @param range Range the client wanted to retrieve
+     * @exception IOException if an input/output error occurs
+     */
+    public static void copy(File cacheEntry, ServletOutputStream ostream,
+                      Range range)
+        throws IOException {
+
+        IOException exception = null;
+
+        InputStream resourceInputStream = new FileInputStream(cacheEntry);
+        InputStream istream =
+            new BufferedInputStream(resourceInputStream, input);
+        exception = CopyUtils.copyRange(istream, ostream, range.start, range.end);
+
+        // Clean up the input stream
+        try {
+            istream.close();
+        } catch (Throwable t) {
+            ;
+        }
+
+        // Rethrow any exception that has occurred
+        if (exception != null)
+            throw exception;
+
+    }
+
+    /**
+     * Copy the contents of the specified input stream to the specified
+     * output stream, and ensure that both streams are closed before returning
+     * (even in the face of an exception).
+     *
+     * @param resourceInfo The ResourceInfo object
+     * @param writer The writer to write to
+     * @param range Range the client wanted to retrieve
+     * @exception IOException if an input/output error occurs
+     */
+    public static void copy(File cacheEntry, PrintWriter writer,
+                            Range range, String fileEncoding)
+        throws IOException {
+
+        IOException exception = null;
+
+        InputStream resourceInputStream = new FileInputStream(cacheEntry);
+
+        Reader reader;
+        if (fileEncoding == null) {
+            reader = new InputStreamReader(resourceInputStream);
+        } else {
+            reader = new InputStreamReader(resourceInputStream,
+                                           fileEncoding);
+        }
+
+        exception = CopyUtils.copyRange(reader, writer, range.start, range.end);
+
+        // Clean up the input stream
+        try {
+            reader.close();
+        } catch (Throwable t) {
+            ;
+        }
+
+        // Rethrow any exception that has occurred
+        if (exception != null)
+            throw exception;
+
+    }
+}

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/MD5Encoder.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/MD5Encoder.java?view=auto&rev=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/MD5Encoder.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/MD5Encoder.java Tue May  1 19:22:45 2007
@@ -0,0 +1,70 @@
+/*
+ * 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.servlets.file;
+
+
+/**
+ * Encode an MD5 digest into a String.
+ * <p>
+ * The 128 bit MD5 hash is converted into a 32 character long String.
+ * Each character of the String is the hexadecimal representation of 4 bits
+ * of the digest.
+ *
+ * @author Remy Maucherat
+ */
+
+public final class MD5Encoder {
+
+
+    // ----------------------------------------------------- Instance Variables
+
+
+    private static final char[] hexadecimal =
+    {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+     'a', 'b', 'c', 'd', 'e', 'f'};
+
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * Encodes the 128 bit (16 bytes) MD5 into a 32 character String.
+     *
+     * @param binaryData Array containing the digest
+     * @return Encoded MD5, or null if encoding failed
+     */
+    public String encode( byte[] binaryData ) {
+
+        if (binaryData.length != 16)
+            return null;
+
+        char[] buffer = new char[32];
+
+        for (int i=0; i<16; i++) {
+            int low = (int) (binaryData[i] & 0x0f);
+            int high = (int) ((binaryData[i] & 0xf0) >> 4);
+            buffer[i*2] = hexadecimal[high];
+            buffer[i*2 + 1] = hexadecimal[low];
+        }
+
+        return new String(buffer);
+
+    }
+
+
+}
+

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/URLEncoder.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/URLEncoder.java?view=auto&rev=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/URLEncoder.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/URLEncoder.java Tue May  1 19:22:45 2007
@@ -0,0 +1,100 @@
+/*
+ * 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.servlets.file;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.util.BitSet;
+
+/**
+ *
+ * This class is very similar to the java.net.URLEncoder class.
+ *
+ * Unfortunately, with java.net.URLEncoder there is no way to specify to the 
+ * java.net.URLEncoder which characters should NOT be encoded.
+ *
+ * This code was moved from DefaultServlet.java
+ *
+ * @author Craig R. McClanahan
+ * @author Remy Maucherat
+ */
+public class URLEncoder {
+    protected static final char[] hexadecimal =
+    {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+     'A', 'B', 'C', 'D', 'E', 'F'};
+
+    //Array containing the safe characters set.
+    protected BitSet safeCharacters = new BitSet(256);
+
+    public URLEncoder() {
+        for (char i = 'a'; i <= 'z'; i++) {
+            addSafeCharacter(i);
+        }
+        for (char i = 'A'; i <= 'Z'; i++) {
+            addSafeCharacter(i);
+        }
+        for (char i = '0'; i <= '9'; i++) {
+            addSafeCharacter(i);
+        }
+    }
+
+    public void addSafeCharacter( char c ) {
+	safeCharacters.set( c );
+    }
+
+    public String encode( String path ) {
+        int maxBytesPerChar = 10;
+        int caseDiff = ('a' - 'A');
+        StringBuffer rewrittenPath = new StringBuffer(path.length());
+        ByteArrayOutputStream buf = new ByteArrayOutputStream(maxBytesPerChar);
+        OutputStreamWriter writer = null;
+        try {
+            writer = new OutputStreamWriter(buf, "UTF8");
+        } catch (Exception e) {
+            e.printStackTrace();
+            writer = new OutputStreamWriter(buf);
+        }
+
+        for (int i = 0; i < path.length(); i++) {
+            int c = (int) path.charAt(i);
+            if (safeCharacters.get(c)) {
+                rewrittenPath.append((char)c);
+            } else {
+                // convert to external encoding before hex conversion
+                try {
+                    writer.write((char)c);
+                    writer.flush();
+                } catch(IOException e) {
+                    buf.reset();
+                    continue;
+                }
+                byte[] ba = buf.toByteArray();
+                for (int j = 0; j < ba.length; j++) {
+                    // Converting each byte in the buffer
+                    byte toEncode = ba[j];
+                    rewrittenPath.append('%');
+                    int low = (int) (toEncode & 0x0f);
+                    int high = (int) ((toEncode & 0xf0) >> 4);
+                    rewrittenPath.append(hexadecimal[high]);
+                    rewrittenPath.append(hexadecimal[low]);
+                }
+                buf.reset();
+            }
+        }
+        return rewrittenPath.toString();
+    }
+}



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


Mime
View raw message