- added new methods stups from servlet, so it compiles
authorcostin <costin@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 25 Jun 2009 15:00:52 +0000 (15:00 +0000)
committercostin <costin@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 25 Jun 2009 15:00:52 +0000 (15:00 +0000)
- removed all deps on coyote, it can now run with the new async connector from sandbox ( still need to update ). Coyote is still the default
- various cleanups in the simple/example integration support
- still passes all watchdog servlet and all but 7 jsp tests
- more separation between the servlets/filters and the engine - and few tweaks to allow file servlet to be used in other containers.

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@788376 13f79535-47bb-0310-9956-ffa450edef68

42 files changed:
modules/tomcat-lite/java/org/apache/tomcat/addons/Filesystem.java [new file with mode: 0644]
modules/tomcat-lite/java/org/apache/tomcat/integration/ObjectManager.java
modules/tomcat-lite/java/org/apache/tomcat/integration/ObjectManagerSpi.java [deleted file]
modules/tomcat-lite/java/org/apache/tomcat/integration/jmx/JmxObjectManagerSpi.java
modules/tomcat-lite/java/org/apache/tomcat/integration/simple/LocalFilesystem.java [new file with mode: 0644]
modules/tomcat-lite/java/org/apache/tomcat/integration/simple/Main.java [new file with mode: 0644]
modules/tomcat-lite/java/org/apache/tomcat/integration/simple/ServletHelper.java [new file with mode: 0644]
modules/tomcat-lite/java/org/apache/tomcat/integration/simple/SimpleObjectManager.java
modules/tomcat-lite/java/org/apache/tomcat/lite/BodyReader.java [new file with mode: 0644]
modules/tomcat-lite/java/org/apache/tomcat/lite/BodyWriter.java [new file with mode: 0644]
modules/tomcat-lite/java/org/apache/tomcat/lite/ClientAbortException.java [new file with mode: 0644]
modules/tomcat-lite/java/org/apache/tomcat/lite/Connector.java
modules/tomcat-lite/java/org/apache/tomcat/lite/ServletContextImpl.java
modules/tomcat-lite/java/org/apache/tomcat/lite/ServletOutputStreamImpl.java
modules/tomcat-lite/java/org/apache/tomcat/lite/ServletRequestImpl.java
modules/tomcat-lite/java/org/apache/tomcat/lite/ServletResponseImpl.java
modules/tomcat-lite/java/org/apache/tomcat/lite/TomcatLite.java
modules/tomcat-lite/java/org/apache/tomcat/lite/cli/Main.java [deleted file]
modules/tomcat-lite/java/org/apache/tomcat/lite/config.properties
modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/ClientAbortException.java [deleted file]
modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/CoyoteConnector.java [new file with mode: 0644]
modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/CoyoteHttp.java [deleted file]
modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/CoyoteServer.java [deleted file]
modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/CoyoteUtils.java [deleted file]
modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/MapperAdapter.java [deleted file]
modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/MessageReader.java [deleted file]
modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/MessageWriter.java [deleted file]
modules/tomcat-lite/java/org/apache/tomcat/lite/webxml/TomcatLiteWebXmlConfig.java
modules/tomcat-lite/java/org/apache/tomcat/lite/webxml/WebXml.java
modules/tomcat-lite/java/org/apache/tomcat/servlets/file/DefaultServlet.java
modules/tomcat-lite/java/org/apache/tomcat/servlets/file/WebdavServlet.java
modules/tomcat-lite/java/org/apache/tomcat/servlets/jsp/JasperCompilerTemplateClassMapper.java
modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/BasicAuthentication.java
modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/FormAuthentication.java
modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/SimpleUserAuthDB.java
modules/tomcat-lite/java/org/apache/tomcat/servlets/session/HttpSessionImpl.java
modules/tomcat-lite/java/org/apache/tomcat/servlets/session/RandomGenerator.java
modules/tomcat-lite/java/org/apache/tomcat/servlets/session/SimpleSessionManager.java
modules/tomcat-lite/java/org/apache/tomcat/util/http/HttpRequest.java [new file with mode: 0644]
modules/tomcat-lite/java/org/apache/tomcat/util/http/HttpResponse.java [new file with mode: 0644]
modules/tomcat-lite/java/org/apache/tomcat/util/http/MimeMap.java [new file with mode: 0644]
modules/tomcat-lite/java/org/apache/tomcat/util/http/mapper/BaseMapper.java

diff --git a/modules/tomcat-lite/java/org/apache/tomcat/addons/Filesystem.java b/modules/tomcat-lite/java/org/apache/tomcat/addons/Filesystem.java
new file mode 100644 (file)
index 0000000..963d06b
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ */
+package org.apache.tomcat.addons;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/** 
+ * Abstract the filesystem - lighter than the JNDI used in catalina.
+ * 
+ * This can be used to port the File/Dav servlets to environments that 
+ * don't have a file system access, or in servlet engines with class-based 
+ * sandboxing.
+ */
+public class Filesystem {
+
+    public OutputStream getOutputStream(String name) throws IOException {
+        return null;
+    }
+
+    public InputStream getInputStream(String name) throws IOException {
+        return new FileInputStream(name);
+    }
+}
index 88d4c6a..e1d8cc2 100644 (file)
@@ -36,7 +36,7 @@ public class ObjectManager {
      * The framework may inject properties - if it supports that.
      */
     public void bind(String name, Object o) {
-        for (ObjectManagerSpi p : providers) {
+        for (ObjectManager p : children) {
             p.bind(name, o);
         }
     }
@@ -45,7 +45,7 @@ public class ObjectManager {
      * When an object is no longer in use.
      */
     public void unbind(String name) {
-        for (ObjectManagerSpi p : providers) {
+        for (ObjectManager p : children) {
             p.unbind(name);
         }        
     }
@@ -54,7 +54,7 @@ public class ObjectManager {
      * Create or get a new object with the given name.
      */
     public Object get(String key) {
-        for (ObjectManagerSpi p : providers) {
+        for (ObjectManager p : children) {
             Object o = p.get(key);
             if (o != null) {
                 return o;
@@ -74,6 +74,10 @@ public class ObjectManager {
      * ObjectManager delegates to providers. You can have multiple
      * providers - for example JMX, DI and OSGI at the same time.
      */
-    protected List<ObjectManagerSpi> providers = 
-        new ArrayList<ObjectManagerSpi>(); 
+    protected List<ObjectManager> children = 
+        new ArrayList<ObjectManager>(); 
+    
+    public void register(ObjectManager om) {
+        om.children.add(this);
+    }    
 }
diff --git a/modules/tomcat-lite/java/org/apache/tomcat/integration/ObjectManagerSpi.java b/modules/tomcat-lite/java/org/apache/tomcat/integration/ObjectManagerSpi.java
deleted file mode 100644 (file)
index 3619087..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- */
-package org.apache.tomcat.integration;
-
-/**
- * Base class for framework-integration plugins.
- */
-public abstract class ObjectManagerSpi {
-    public abstract void bind(String name, Object o);
-    
-    public abstract void unbind(String name);
-
-    public abstract Object get(String key);
-
-    public void register(ObjectManager om) {
-        om.providers.add(this);
-    }
-}
\ No newline at end of file
index 96b1347..0a1b1ba 100644 (file)
@@ -4,7 +4,7 @@ package org.apache.tomcat.integration.jmx;
 
 import java.util.logging.Logger;
 
-import org.apache.tomcat.integration.ObjectManagerSpi;
+import org.apache.tomcat.integration.ObjectManager;
 import org.apache.tomcat.util.modeler.Registry;
 
 /**
@@ -12,7 +12,7 @@ import org.apache.tomcat.util.modeler.Registry;
  * 
  * All objects of interest are registered automatically.
  */
-public class JmxObjectManagerSpi extends ObjectManagerSpi {
+public class JmxObjectManagerSpi extends ObjectManager {
     Registry registry;
     Logger log = Logger.getLogger("JmxObjectManager");
     
diff --git a/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/LocalFilesystem.java b/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/LocalFilesystem.java
new file mode 100644 (file)
index 0000000..782d5c2
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ */
+package org.apache.tomcat.integration.simple;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.tomcat.addons.Filesystem;
+
+public class LocalFilesystem extends Filesystem {
+
+    public OutputStream getOutputStream(String name) throws IOException {
+        return new FileOutputStream(name);
+    }    
+}
diff --git a/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/Main.java b/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/Main.java
new file mode 100644 (file)
index 0000000..7871cbb
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ */
+package org.apache.tomcat.integration.simple;
+
+import org.apache.tomcat.integration.ObjectManager;
+
+/**
+ * Replacement for tomcat-lite specific Main, using the simple 
+ * injection. SimpleObjectManager also has support for simple 
+ * command line processing - CLI is treated the same with 
+ * properties from the config file. 
+ * 
+ * @author Costin Manolache
+ */
+public class Main {
+
+    public static void main(String args[]) 
+    throws Exception {
+        SimpleObjectManager om = new SimpleObjectManager();
+        
+        // Will process CLI. 
+        // 'config' will load a config file.
+        om.bind("Main.args", args);
+
+        Runnable main = (Runnable) om.get("Main");
+        if (main == null) {
+            // TODO: look for a pre-defined name in local dir, resource,
+            // manifest
+            System.err.println("Using default tomcat-lite configuration");
+
+            if (args.length == 0) {
+                System.err.println("Example command line:");
+                System.err.println("-context /:webapps/ROOT -Connector.port 9999");
+            }
+            
+            String cfgFile = "org/apache/tomcat/lite/config.properties";
+            om.loadResource(cfgFile);
+            main = (Runnable) om.get("Main");
+        }
+        
+        // add JMX support
+        ObjectManager jmx = (ObjectManager) om.get("JMX");
+        if (jmx != null) {
+            jmx.register(om);
+        }
+
+        main.run();
+
+    }    
+}
diff --git a/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/ServletHelper.java b/modules/tomcat-lite/java/org/apache/tomcat/integration/simple/ServletHelper.java
new file mode 100644 (file)
index 0000000..bf5bf15
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ */
+package org.apache.tomcat.integration.simple;
+
+import java.util.Enumeration;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+
+import org.apache.tomcat.integration.ObjectManager;
+
+public class ServletHelper {
+
+    public static ObjectManager getObjectManager(ServletContext ctx) {
+        // May be provided by container or a listener
+        ObjectManager om = (ObjectManager) ctx.getAttribute(ObjectManager.ATTRIBUTE);
+        if (om == null) {
+            // Default
+            SimpleObjectManager som = new SimpleObjectManager();
+            om = som;
+            
+            // All context init params are set
+            Enumeration namesE = ctx.getInitParameterNames();
+            while (namesE.hasMoreElements()) {
+                String n = (String) namesE.nextElement();
+                String v = ctx.getInitParameter(n);
+                som.getProperties().put(n, v);
+            }
+            
+            ctx.setAttribute(ObjectManager.ATTRIBUTE, om);
+            // load context settings
+        }
+        return om;
+    }
+
+    public static void initServlet(Servlet s) {
+        ServletConfig sc = s.getServletConfig();
+        String name = sc.getServletName();
+        String ctx = sc.getServletContext().getContextPath();
+        
+        // Servlets are named:...
+        
+        ObjectManager om = getObjectManager(sc.getServletContext());
+        
+        String dn = ctx + ":" + name;
+        
+        // If SimpleObjectManager ( or maybe other supporting dynamic config ):
+        if (om instanceof SimpleObjectManager) {
+            SimpleObjectManager som = (SimpleObjectManager) om;
+            
+            
+        }
+        
+        
+        om.bind(dn, s);
+        
+    }
+    
+}
index 5b33983..20854a5 100644 (file)
@@ -2,6 +2,7 @@
  */
 package org.apache.tomcat.integration.simple;
 
+import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -11,8 +12,8 @@ import java.util.Properties;
 import java.util.logging.Logger;
 
 import org.apache.tomcat.integration.ObjectManager;
-import org.apache.tomcat.integration.ObjectManagerSpi;
 import org.apache.tomcat.util.IntrospectionUtils;
+import org.apache.tools.ant.taskdefs.LoadResource;
 
 /**
  * This is a very small 'dependency injection'/registry poor-man substitute, 
@@ -39,36 +40,30 @@ import org.apache.tomcat.util.IntrospectionUtils;
  * 
  * @author Costin Manolache
  */
-public class SimpleObjectManager extends ObjectManagerSpi {
-
+public class SimpleObjectManager extends ObjectManager {
     static Logger log = Logger.getLogger(SimpleObjectManager.class.getName());
     
-    /** 
-     * Saved CLI arguments. Will be added to the properties.
-     */
-    public static String[] args;
-    
     protected Properties props = new Properties();
     protected Map<String, Object> objects = new HashMap();
     ObjectManager om;
     
     public SimpleObjectManager() {
+        // Register PropertiesSpi
     }
 
-    public SimpleObjectManager(ObjectManager om) {
-        register(om);
+    public SimpleObjectManager(String[] args) {
+        this();
+        bind("Main.args", args);
     }
-
+    
+    public void loadResource(String res) {
+        InputStream in = this.getClass().getClassLoader()
+            .getResourceAsStream(res);
+        load(in);
+    }
+    
     public void register(ObjectManager om) {
         this.om = om;
-        if (args != null) {
-            try {
-                processArgs(args, props);
-            } catch (IOException e) {
-                // TODO Auto-generated catch block
-                e.printStackTrace();
-            }
-        }
         super.register(om);
     }
     
@@ -84,12 +79,6 @@ public class SimpleObjectManager extends ObjectManagerSpi {
         }
     }
     
-    public void loadResource(String res) {
-        InputStream in = this.getClass().getClassLoader()
-            .getResourceAsStream(res);
-        load(in);
-    }
-    
     public Properties getProperties() {
         return props;
     }
@@ -100,8 +89,16 @@ public class SimpleObjectManager extends ObjectManagerSpi {
 
     @Override
     public void bind(String name, Object o) {
-        log.info("Bound: " + name + " " + o);
+        //log.info("Bound: " + name + " " + o);
 
+        if ("Main.args".equals(name)) {
+            try {
+                processArgs((String[]) o, props);
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        
         // TODO: can I make 'inject' public - Guice seems to 
         // support this.
         inject(name, o);
@@ -170,7 +167,7 @@ public class SimpleObjectManager extends ObjectManagerSpi {
      * @return everything after the first non arg not starting with '-'
      * @throws IOException 
      */
-    public static String[] processArgs(String[] args, Properties props) 
+    public String[] processArgs(String[] args, Properties props) 
             throws IOException {
 
         for (int i = 0; i < args.length; i++) {
@@ -200,15 +197,15 @@ public class SimpleObjectManager extends ObjectManagerSpi {
             }
 
             if ("config".equals(arg)) {
-                props.load(new FileInputStream(value));
+                if (new File(value).exists()) {
+                    load(new FileInputStream(value));                    
+                } else {
+                    loadResource(value);
+                }
             } else {
                 props.put(name, value);
             }
         }
         return new String[] {};
-    }
-
-    public static void setArgs(String[] argv) {
-        SimpleObjectManager.args = argv;
-    }
+    }    
 }
diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/BodyReader.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/BodyReader.java
new file mode 100644 (file)
index 0000000..e8f8a6b
--- /dev/null
@@ -0,0 +1,509 @@
+/*
+ * 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.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.HashMap;
+
+import org.apache.tomcat.util.buf.B2CConverter;
+import org.apache.tomcat.util.buf.ByteChunk;
+import org.apache.tomcat.util.buf.CharChunk;
+
+/**
+ * Refactored from catalina.connector.InputBuffer. Renamed to avoid conflict
+ * with coyote class.
+ * 
+ */
+
+/**
+ * The buffer used by Tomcat request. This is a derivative of the Tomcat 3.3
+ * OutputBuffer, adapted to handle input instead of output. This allows 
+ * complete recycling of the facade objects (the ServletInputStream and the
+ * BufferedReader).
+ *
+ * @author Remy Maucherat
+ */
+public class BodyReader extends Reader
+    implements ByteChunk.ByteInputChannel, CharChunk.CharInputChannel,
+               CharChunk.CharOutputChannel {
+
+
+    // -------------------------------------------------------------- Constants
+
+
+    public static final String DEFAULT_ENCODING = 
+        org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING;
+    public static final int DEFAULT_BUFFER_SIZE = 8*1024;
+
+    // The buffer can be used for byte[] and char[] reading
+    // ( this is needed to support ServletInputStream and BufferedReader )
+    public final int INITIAL_STATE = 0;
+    public final int CHAR_STATE = 1;
+    public final int BYTE_STATE = 2;
+
+
+    // ----------------------------------------------------- Instance Variables
+
+
+    /**
+     * The byte buffer. More data may be added to it while reading.
+     */
+    private ByteChunk bb;
+
+
+    /**
+     * The chunk buffer, will be filled in from the bb.
+     */
+    private CharChunk cb;
+
+
+    /**
+     * State of the output buffer.
+     */
+    private int state = 0;
+
+
+    /**
+     * Number of bytes read.
+     */
+    private int bytesRead = 0;
+
+
+    /**
+     * Number of chars read.
+     */
+    private int charsRead = 0;
+
+
+    /**
+     * Flag which indicates if the input buffer is closed.
+     */
+    private boolean closed = false;
+
+    /**
+     * Encoding to use.
+     */
+    private String enc;
+
+
+    /**
+     * Encoder is set.
+     */
+    private boolean gotEnc = false;
+
+
+    /**
+     * Cached encoders.
+     */
+    protected HashMap<String, B2CConverter> encoders = 
+      new HashMap<String, B2CConverter>();
+
+
+    /**
+     * Current byte to char converter.
+     */
+    protected B2CConverter conv;
+
+
+    /**
+     * Associated Coyote request.
+     */
+    private ServletRequestImpl coyoteRequest;
+    Connector connector;
+
+    /**
+     * Buffer position.
+     */
+    private int markPos = -1;
+
+
+    /**
+     * Buffer size.
+     */
+    private int size = -1;
+
+
+    // ----------------------------------------------------------- Constructors
+
+
+    /**
+     * Default constructor. Allocate the buffer with the default buffer size.
+     */
+    public BodyReader() {
+        this(DEFAULT_BUFFER_SIZE);
+    }
+
+
+    /**
+     * Alternate constructor which allows specifying the initial buffer size.
+     * 
+     * @param size Buffer size to use
+     */
+    public BodyReader(int size) {
+        this.size = size;
+        bb = new ByteChunk(size);
+        bb.setLimit(size);
+        bb.setByteInputChannel(this);
+        cb = new CharChunk(size);
+        cb.setLimit(size);
+        cb.setOptimizedWrite(false);
+        cb.setCharInputChannel(this);
+        cb.setCharOutputChannel(this);
+    }
+
+
+    // ------------------------------------------------------------- Properties
+
+
+    /**
+     * Associated Coyote request.
+     * 
+     * @param coyoteRequest Associated Coyote request
+     */
+    public void setConnector(Connector c, ServletRequestImpl coyoteRequest) {
+        this.connector = c;
+        this.coyoteRequest = coyoteRequest;
+    }
+
+
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * Recycle the output buffer.
+     */
+    public void recycle() {
+        
+        state = INITIAL_STATE;
+        bytesRead = 0;
+        charsRead = 0;
+        
+        // If usage of mark made the buffer too big, reallocate it
+        if (cb.getChars().length > size) {
+            cb = new CharChunk(size);
+            cb.setLimit(size);
+            cb.setCharInputChannel(this);
+            cb.setCharOutputChannel(this);
+        } else {
+            cb.recycle();
+        }
+        markPos = -1;
+        bb.recycle(); 
+        closed = false;
+        
+        if (conv != null) {
+            conv.recycle();
+        }
+        
+        gotEnc = false;
+        enc = null;
+        
+    }
+
+
+    /**
+     * Close the input buffer.
+     * 
+     * @throws IOException An underlying IOException occurred
+     */
+    public void close()
+        throws IOException {
+        closed = true;
+    }
+
+
+    public int available()
+        throws IOException {
+        if (state == BYTE_STATE) {
+            return bb.getLength();
+        } else if (state == CHAR_STATE) {
+            return cb.getLength();
+        } else {
+            return 0;
+        }
+    }
+
+
+    // ------------------------------------------------- Bytes Handling Methods
+
+
+    /** 
+     * Reads new bytes in the byte chunk.
+     * 
+     * @param cbuf Byte buffer to be written to the response
+     * @param off Offset
+     * @param len Length
+     * 
+     * @throws IOException An underlying IOException occurred
+     */
+    public int realReadBytes(byte cbuf[], int off, int len)
+       throws IOException {
+
+        if (closed)
+            return -1;
+        if (coyoteRequest == null)
+            return -1;
+
+        state = BYTE_STATE;
+
+        int result = connector.doRead(coyoteRequest, bb);
+
+        return result;
+
+    }
+
+
+    public int readByte()
+        throws IOException {
+        return bb.substract();
+    }
+
+
+    public int read(byte[] b, int off, int len)
+        throws IOException {
+        return bb.substract(b, off, len);
+    }
+
+
+    // ------------------------------------------------- Chars Handling Methods
+
+
+    /**
+     * Since the converter will use append, it is possible to get chars to
+     * be removed from the buffer for "writing". Since the chars have already
+     * been read before, they are ignored. If a mark was set, then the
+     * mark is lost.
+     */
+    public void realWriteChars(char c[], int off, int len) 
+        throws IOException {
+        markPos = -1;
+    }
+
+
+    public void setEncoding(String s) {
+        enc = s;
+    }
+
+    /** 
+     * Called when a read(char[]) operation is lacking data. It will read
+     * bytes.
+     */
+    public int realReadChars(char cbuf[], int off, int len)
+        throws IOException {
+
+        if (!gotEnc)
+            setConverter();
+
+        if (bb.getLength() <= 0) {
+            int nRead = realReadBytes(bb.getBytes(), 0, bb.getBytes().length);
+            if (nRead < 0) {
+                return -1;
+            }
+        }
+
+        if (markPos == -1) {
+            cb.setOffset(0);
+            cb.setEnd(0);
+        }
+
+        conv.convert(bb, cb, -1);
+        bb.setOffset(bb.getEnd());
+        state = CHAR_STATE;
+
+        return cb.getLength();
+
+    }
+
+
+    public int read()
+        throws IOException {
+        return cb.substract();
+    }
+
+
+    public int read(char[] cbuf)
+        throws IOException {
+        return read(cbuf, 0, cbuf.length);
+    }
+
+
+    public int read(char[] cbuf, int off, int len)
+        throws IOException {
+        return cb.substract(cbuf, off, len);
+    }
+
+
+    public long skip(long n)
+        throws IOException {
+
+        if (n < 0) {
+            throw new IllegalArgumentException();
+        }
+
+        long nRead = 0;
+        while (nRead < n) {
+            if (cb.getLength() >= n) {
+                cb.setOffset(cb.getStart() + (int) n);
+                nRead = n;
+            } else {
+                nRead += cb.getLength();
+                cb.setOffset(cb.getEnd());
+                int toRead = 0;
+                if (cb.getChars().length < (n - nRead)) {
+                    toRead = cb.getChars().length;
+                } else {
+                    toRead = (int) (n - nRead);
+                }
+                int nb = realReadChars(cb.getChars(), 0, toRead);
+                if (nb < 0)
+                    break;
+            }
+        }
+
+        return nRead;
+
+    }
+
+
+    public boolean ready()
+        throws IOException {
+        return (cb.getLength() > 0);
+    }
+
+
+    public boolean markSupported() {
+        return true;
+    }
+
+
+    public void mark(int readAheadLimit)
+        throws IOException {
+        if (cb.getLength() <= 0) {
+            cb.setOffset(0);
+            cb.setEnd(0);
+        } else {
+            if ((cb.getBuffer().length > (2 * size)) 
+                && (cb.getLength()) < (cb.getStart())) {
+                System.arraycopy(cb.getBuffer(), cb.getStart(), 
+                                 cb.getBuffer(), 0, cb.getLength());
+                cb.setEnd(cb.getLength());
+                cb.setOffset(0);
+            }
+        }
+        int offset = readAheadLimit;
+        if (offset < size) {
+            offset = size;
+        }
+        cb.setLimit(cb.getStart() + offset);
+        markPos = cb.getStart();
+    }
+
+
+    public void reset()
+        throws IOException {
+        if (state == CHAR_STATE) {
+            if (markPos < 0) {
+                cb.recycle();
+                markPos = -1;
+                throw new IOException();
+            } else {
+                cb.setOffset(markPos);
+            }
+        } else {
+            bb.recycle();
+        }
+    }
+
+
+    protected void setConverter()
+        throws IOException {
+        if (coyoteRequest != null)
+            enc = coyoteRequest.getCharacterEncoding();
+
+        gotEnc = true;
+        if (enc == null)
+            enc = DEFAULT_ENCODING;
+        conv = (B2CConverter) encoders.get(enc);
+        if (conv == null) {
+          conv = new B2CConverter(enc);
+          encoders.put(enc, conv);
+        }
+    }
+    
+    public class MRInputStream extends InputStream {
+        public long skip(long n)
+                throws IOException {
+            return BodyReader.this.skip(n);
+        }
+
+        public void mark(int readAheadLimit)
+        {
+            try {
+                BodyReader.this.mark(readAheadLimit);
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+
+        public void reset()
+        throws IOException {
+            BodyReader.this.reset();
+        }
+
+
+
+        public int read()
+        throws IOException {    
+            return BodyReader.this.readByte();
+        }
+
+        public int available() throws IOException {
+            return BodyReader.this.available();
+        }
+
+        public int read(final byte[] b) throws IOException {
+            return BodyReader.this.read(b, 0, b.length);
+        }
+
+
+        public int read(final byte[] b, final int off, final int len)
+        throws IOException {
+
+            return BodyReader.this.read(b, off, len);
+        }
+
+
+        /** 
+         * Close the stream
+         * Since we re-cycle, we can't allow the call to super.close()
+         * which would permantely disable us.
+         */
+        public void close() throws IOException {
+            BodyReader.this.close();
+        }
+    }
+    
+    MRInputStream is = new MRInputStream();
+    
+    public InputStream asInputStream() {
+        return is;
+    }
+}
diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/BodyWriter.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/BodyWriter.java
new file mode 100644 (file)
index 0000000..cad571d
--- /dev/null
@@ -0,0 +1,656 @@
+/*
+ */
+package org.apache.tomcat.lite;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.HashMap;
+
+import org.apache.tomcat.util.buf.ByteChunk;
+import org.apache.tomcat.util.buf.C2BConverter;
+import org.apache.tomcat.util.buf.CharChunk;
+
+/**
+ * Implement buffering and character translation acording to the 
+ * servlet spec.  
+ * 
+ * This class handles both chars and bytes.
+ * 
+ * It is tightly integrated with servlet response, sending headers
+ * and updating the commit state.
+ * 
+ * TODO: add 'extension' interface that allows direct access to 
+ * the async connector non-copy non-blocking queue. Same for the 
+ * OutputStream. Maybe switch the buffer to the brigade. 
+ * 
+ * @author Costin Manolache
+ */
+public class BodyWriter extends Writer {
+
+    // used in getWriter, until a method is added to res.
+    protected static final int WRITER_NOTE = 3;
+
+
+    private ByteChunk.ByteOutputChannel byteFlusher = 
+        new ByteChunk.ByteOutputChannel() {
+
+        @Override
+        public void realWriteBytes(byte[] cbuf, int off, int len)
+                throws IOException {
+            BodyWriter.this.realWriteBytes(cbuf, off, len);
+        }
+    };
+
+    private CharChunk.CharOutputChannel charFlusher = 
+        new CharChunk.CharOutputChannel() {
+        @Override
+        public void realWriteChars(char[] cbuf, int off, int len)
+                throws IOException {
+            BodyWriter.this.realWriteChars(cbuf, off, len);
+        }
+    };
+    
+
+    public static final String DEFAULT_ENCODING = 
+        org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING;
+    public static final int DEFAULT_BUFFER_SIZE = 8*1024;
+
+
+    // The buffer can be used for byte[] and char[] writing
+    // ( this is needed to support ServletOutputStream and for
+    // efficient implementations of templating systems )
+    public final int CHAR_STATE = 1;
+    public final int BYTE_STATE = 2;
+
+    boolean headersSent = false;
+    // ----------------------------------------------------- Instance Variables
+    ServletResponseImpl res;
+
+    /**
+     * The byte buffer.
+     */
+    protected ByteChunk bb;
+
+
+    /**
+     * The chunk buffer.
+     */
+    protected CharChunk cb;
+
+
+    /**
+     * State of the output buffer.
+     */
+    protected int state = 0;
+
+
+    /**
+     * Number of bytes written.
+     */
+    protected int bytesWritten = 0;
+
+
+    /**
+     * Number of chars written.
+     */
+    protected int charsWritten = 0;
+
+
+    /**
+     * Flag which indicates if the output buffer is closed.
+     */
+    protected boolean closed = false;
+
+
+    /**
+     * Do a flush on the next operation.
+     */
+    protected boolean doFlush = false;
+
+
+    /**
+     * Byte chunk used to output bytes. This is just used to wrap the byte[]
+     * to match the coyote OutputBuffer interface
+     */
+    protected ByteChunk outputChunk = new ByteChunk();
+
+
+    /**
+     * Encoding to use. 
+     * TODO: isn't it redundant ? enc, gotEnc, conv plus the enc in the bb
+     */
+    protected String enc;
+
+
+    /**
+     * Encoder is set.
+     */
+    protected boolean gotEnc = false;
+
+
+    /**
+     * List of encoders. The writer is reused - the encoder mapping 
+     * avoids creating expensive objects. In future it'll contain nio.Charsets
+     */
+    protected HashMap encoders = new HashMap();
+
+
+    /**
+     * Current char to byte converter. TODO: replace with Charset
+     */
+    protected C2BConverter conv;
+
+    /**
+     * Suspended flag. All output bytes will be swallowed if this is true.
+     */
+    protected boolean suspended = false;
+
+    private Connector connector;
+
+
+    // ----------------------------------------------------------- Constructors
+
+
+    /**
+     * Default constructor. Allocate the buffer with the default buffer size.
+     */
+    public BodyWriter() {
+
+        this(DEFAULT_BUFFER_SIZE);
+
+    }
+
+
+    /**
+     * Alternate constructor which allows specifying the initial buffer size.
+     * 
+     * @param size Buffer size to use
+     */
+    public BodyWriter(int size) {
+
+        bb = new ByteChunk(size);
+        bb.setLimit(size);
+        bb.setByteOutputChannel(byteFlusher);
+        cb = new CharChunk(size);
+        cb.setCharOutputChannel(charFlusher);
+        cb.setLimit(size);
+
+    }
+    
+    public void setConnector(Connector c, ServletResponseImpl res) {
+        this.res = res;
+        this.connector = c;
+    }
+
+
+    // ------------------------------------------------------------- Properties
+
+
+    /**
+     * Is the response output suspended ?
+     * 
+     * @return suspended flag value
+     */
+    public boolean isSuspended() {
+        return this.suspended;
+    }
+
+
+    /**
+     * Set the suspended flag.
+     * 
+     * @param suspended New suspended flag value
+     */
+    public void setSuspended(boolean suspended) {
+        this.suspended = suspended;
+    }
+
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * Recycle the output buffer.
+     */
+    public void recycle() {
+        
+        state = BYTE_STATE;
+        headersSent = false;
+        bytesWritten = 0;
+        charsWritten = 0;
+        
+        cb.recycle();
+        bb.recycle(); 
+        closed = false;
+        suspended = false;
+        
+        if (conv!= null) {
+            conv.recycle();
+        }
+        
+        gotEnc = false;
+        enc = null;
+        
+    }
+
+
+    /**
+     * Close the output buffer. This tries to calculate the response size if 
+     * the response has not been committed yet.
+     * 
+     * @throws IOException An underlying IOException occurred
+     */
+    public void close()
+        throws IOException {
+
+        if (closed)
+            return;
+        if (suspended)
+            return;
+
+        if (state == CHAR_STATE) {
+            cb.flushBuffer();
+            state = BYTE_STATE;
+        }
+        connector.beforeClose(res, bb.getLength());
+
+        doFlush(false);
+        closed = true;
+
+        connector.finishResponse(res);
+    }
+
+
+    /**
+     * Flush bytes or chars contained in the buffer.
+     * 
+     * @throws IOException An underlying IOException occurred
+     */
+    public void flush()
+        throws IOException {
+        doFlush(true);
+    }
+
+    /**
+     * Flush bytes or chars contained in the buffer.
+     * 
+     * @throws IOException An underlying IOException occurred
+     */
+    protected void doFlush(boolean realFlush)
+        throws IOException {
+
+        if (suspended)
+            return;
+
+        doFlush = true;
+        if (!headersSent) {
+            // If the buffers are empty, commit the response header
+            connector.sendHeaders(res);
+            headersSent = true;
+        }
+        if (state == CHAR_STATE) {
+            cb.flushBuffer();
+            state = BYTE_STATE;
+        } 
+        if (state == BYTE_STATE) {
+            bb.flushBuffer();
+        }  
+        doFlush = false;
+
+        if (realFlush) {
+            connector.realFlush(res);
+        }
+
+    }
+
+
+    // ------------------------------------------------- Bytes Handling Methods
+
+
+    /** 
+     * Sends the buffer data to the client output, checking the
+     * state of Response and calling the right interceptors.
+     * 
+     * @param buf Byte buffer to be written to the response
+     * @param off Offset
+     * @param cnt Length
+     * 
+     * @throws IOException An underlying IOException occurred
+     */
+    private void realWriteBytes(byte buf[], int off, int cnt)
+        throws IOException {
+
+        if (closed)
+            return;
+
+        // If we really have something to write
+        if (cnt > 0) {
+            // real write to the adapter
+            outputChunk.setBytes(buf, off, cnt);
+            try {
+                connector.doWrite(res, outputChunk);
+            } catch (IOException e) {
+                // An IOException on a write is almost always due to
+                // the remote client aborting the request.  Wrap this
+                // so that it can be handled better by the error dispatcher.
+                throw new ClientAbortException(e);
+            }
+        }
+
+    }
+
+
+    public void write(byte b[], int off, int len) throws IOException {
+
+        if (suspended)
+            return;
+
+        if (state == CHAR_STATE)
+            cb.flushBuffer();
+        state = BYTE_STATE;
+        writeBytes(b, off, len);
+
+    }
+
+
+    private void writeBytes(byte b[], int off, int len) 
+        throws IOException {
+
+        if (closed)
+            return;
+
+        bb.append(b, off, len);
+        bytesWritten += len;
+
+        // if called from within flush(), then immediately flush
+        // remaining bytes
+        if (doFlush) {
+            bb.flushBuffer();
+        }
+
+    }
+
+
+    public void writeByte(int b)
+        throws IOException {
+
+        if (suspended)
+            return;
+
+        if (state == CHAR_STATE)
+            cb.flushBuffer();
+        state = BYTE_STATE;
+
+        bb.append( (byte)b );
+        bytesWritten++;
+
+    }
+
+
+    // ------------------------------------------------- Chars Handling Methods
+
+
+    public void write(int c)
+        throws IOException {
+
+        if (suspended)
+            return;
+
+        state = CHAR_STATE;
+
+        cb.append((char) c);
+        charsWritten++;
+
+    }
+
+
+    public void write(char c[])
+        throws IOException {
+
+        if (suspended)
+            return;
+
+        write(c, 0, c.length);
+
+    }
+
+
+    public void write(char c[], int off, int len)
+        throws IOException {
+
+        if (suspended)
+            return;
+
+        state = CHAR_STATE;
+
+        cb.append(c, off, len);
+        charsWritten += len;
+
+    }
+
+
+    public void write(StringBuffer sb)
+        throws IOException {
+
+        if (suspended)
+            return;
+
+        state = CHAR_STATE;
+
+        int len = sb.length();
+        charsWritten += len;
+        cb.append(sb);
+
+    }
+
+
+    /**
+     * Append a string to the buffer
+     */
+    public void write(String s, int off, int len)
+        throws IOException {
+
+        if (suspended)
+            return;
+
+        state=CHAR_STATE;
+
+        charsWritten += len;
+        if (s==null)
+            s="null";
+        cb.append( s, off, len );
+
+    }
+
+
+    public void write(String s)
+        throws IOException {
+
+        if (suspended)
+            return;
+
+        state = CHAR_STATE;
+        if (s==null)
+            s="null";
+        write(s, 0, s.length());
+
+    } 
+
+    public void println() throws IOException {
+        write("\n");
+    }
+
+    public void println(String s) throws IOException {
+        write(s);
+        write("\n");
+    }
+
+    public void print(String s) throws IOException {
+        write(s);
+    }
+
+    public void flushChars()
+        throws IOException {
+
+        cb.flushBuffer();
+        state = BYTE_STATE;
+
+    }
+
+
+    public boolean flushCharsNeeded() {
+        return state == CHAR_STATE;
+    }
+
+
+    public void setEncoding(String s) {
+        enc = s;
+    }
+
+
+    private void realWriteChars(char c[], int off, int len) 
+        throws IOException {
+
+        if (!gotEnc)
+            setConverter();
+
+        conv.convert(c, off, len);
+        conv.flushBuffer();     // ???
+
+    }
+
+
+    public void checkConverter() 
+        throws IOException {
+
+        if (!gotEnc)
+            setConverter();
+
+    }
+
+
+    protected void setConverter() 
+        throws IOException {
+
+        enc = res.getCharacterEncoding();
+
+        gotEnc = true;
+        if (enc == null)
+            enc = DEFAULT_ENCODING;
+        conv = (C2BConverter) encoders.get(enc);
+        if (conv == null) {
+            
+            if (System.getSecurityManager() != null){
+                try{
+                    conv = (C2BConverter)AccessController.doPrivileged(
+                            new PrivilegedExceptionAction(){
+
+                                public Object run() throws IOException{
+                                    return new C2BConverter(bb, enc);
+                                }
+
+                            }
+                    );              
+                }catch(PrivilegedActionException ex){
+                    Exception e = ex.getException();
+                    if (e instanceof IOException)
+                        throw (IOException)e; 
+                }
+            } else {
+                conv = new C2BConverter(bb, enc);
+            }
+            
+            encoders.put(enc, conv);
+
+        }
+    }
+
+    
+    // --------------------  BufferedOutputStream compatibility
+
+
+    /**
+     * Real write - this buffer will be sent to the client
+     */
+    public void flushBytes()
+        throws IOException {
+
+        bb.flushBuffer();
+
+    }
+
+
+    public int getBytesWritten() {
+        return bytesWritten;
+    }
+
+
+    public int getCharsWritten() {
+        return charsWritten;
+    }
+
+
+    public int getContentWritten() {
+        return bytesWritten + charsWritten;
+    }
+
+
+    /** 
+     * True if this buffer hasn't been used ( since recycle() ) -
+     * i.e. no chars or bytes have been added to the buffer.  
+     */
+    public boolean isNew() {
+        return (bytesWritten == 0) && (charsWritten == 0);
+    }
+
+
+    public void setBufferSize(int size) {
+        if (size > bb.getLimit()) {// ??????
+            bb.setLimit(size);
+        }
+    }
+
+
+    public void reset() {
+
+        //count=0;
+        bb.recycle();
+        bytesWritten = 0;
+        cb.recycle();
+        charsWritten = 0;
+        gotEnc = false;
+        enc = null;
+        state = BYTE_STATE;
+    }
+
+
+    public int getBufferSize() {
+        return bb.getLimit();
+    }
+
+    public ByteChunk getByteBuffer() {
+      return outputChunk;
+    }
+
+}
+//{
+//    public abstract int getBytesWritten();
+//    public abstract int getCharsWritten();
+//    public abstract void recycle();
+//    public abstract void setSuspended(boolean suspended);
+//    public abstract boolean isSuspended();
+//    
+//    public abstract void reset();
+//    public abstract int getBufferSize();
+//    public abstract void setBufferSize(int n);
+//    public abstract void checkConverter() throws IOException;
+//    public boolean isNew() {
+//        return getBytesWritten() == 0 && getCharsWritten() == 0;
+//    }
+//    public abstract void write(byte[] b, int off, int len) throws IOException;
+//    public abstract void writeByte(int b) throws IOException;
+//    
+//}
\ No newline at end of file
diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/ClientAbortException.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/ClientAbortException.java
new file mode 100644 (file)
index 0000000..0b9f365
--- /dev/null
@@ -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;
+
+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());
+
+    }
+
+
+}
index d104b68..245bfc6 100644 (file)
@@ -8,6 +8,7 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.tomcat.integration.ObjectManager;
+import org.apache.tomcat.util.buf.ByteChunk;
 
 /**
  * What we need to plugin a connector.
@@ -26,11 +27,51 @@ public interface Connector {
 
     public void setDaemon(boolean b);
     
-    public void start();
+    public void start() throws IOException;
     
-    public void stop();
+    public void stop() throws Exception;
     
-    public void finishResponse(HttpServletResponse res) throws IOException;
+    /**
+     * Called during close() - either on explicit output close, or 
+     * after the request is completed. 
+     * 
+     * @throws IOException
+     */
+    public abstract void finishResponse(HttpServletResponse res) throws IOException;
+   
+    /**
+     * Called before flushing the output during close.
+     * Content-Length may be updated.
+     * @param len 
+     * 
+     * @throws IOException
+     */
+    public abstract void beforeClose(HttpServletResponse res, int len) throws IOException;
+    
+    /** 
+     * Called when the first flush() is called.
+     * @throws IOException
+     */
+    public abstract void sendHeaders(HttpServletResponse res) throws IOException;
+    
+    /**
+     * Send data to the client.
+     * @throws IOException
+     */
+    public abstract void realFlush(HttpServletResponse res) throws IOException;
+
+    /**
+     * Write to the connector underlying buffer.
+     * The chunk will be reused (currently).
+     */
+    public abstract void doWrite(HttpServletResponse res, ByteChunk outputChunk2) throws IOException;
+
+    
+    //public void finishResponse(HttpServletResponse res) throws IOException;
+    
+    public void acknowledge(HttpServletResponse res) throws IOException;
+
+    public void reset(HttpServletResponse res);
     
     public void recycle(HttpServletRequest req, HttpServletResponse res);
 
@@ -39,4 +80,10 @@ public interface Connector {
     public void setTomcatLite(TomcatLite tomcatLite);
 
     public void setObjectManager(ObjectManager objectManager);
+    
+    public String getRemoteHost(HttpServletRequest req);
+    
+    public String getRemoteAddr(HttpServletRequest req);
+    
+    public int doRead(ServletRequestImpl coyoteRequest, ByteChunk bb) throws IOException;
 }
index bce77f7..f65866f 100644 (file)
@@ -37,11 +37,11 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
-import java.util.Map.Entry;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import javax.servlet.DispatcherType;
+import javax.servlet.Filter;
+import javax.servlet.FilterRegistration;
 import javax.servlet.RequestDispatcher;
 import javax.servlet.Servlet;
 import javax.servlet.ServletConfig;
@@ -51,8 +51,10 @@ import javax.servlet.ServletContextAttributeListener;
 import javax.servlet.ServletContextEvent;
 import javax.servlet.ServletContextListener;
 import javax.servlet.ServletException;
+import javax.servlet.ServletRegistration;
 import javax.servlet.SessionCookieConfig;
 import javax.servlet.SessionTrackingMode;
+import javax.servlet.FilterRegistration.Dynamic;
 
 import org.apache.tomcat.addons.UserSessionManager;
 import org.apache.tomcat.integration.ObjectManager;
@@ -933,10 +935,8 @@ public class ServletContextImpl implements ServletContext {
     public void processWebAppData(ServletContextConfig d) throws ServletException {
         this.contextConfig = d;
         
-        Iterator i1 = d.mimeMapping.entrySet().iterator();
-        while (i1.hasNext()) {
-            Entry k = (Entry)i1.next();
-            addMimeType((String)k.getKey(), (String)k.getValue());
+        for (String k: d.mimeMapping.keySet()) {
+            addMimeType(k, d.mimeMapping.get(k));            
         }
         
         String[] wFiles = (String[])d.welcomeFileList.toArray(new String[0]);
@@ -976,10 +976,8 @@ public class ServletContextImpl implements ServletContext {
             addServletConfig(sw);
         }
         
-        Iterator i4 = d.servletMapping.entrySet().iterator();
-        while (i4.hasNext()) {
-            Entry/*<String, String>*/ k = (Entry) i4.next();
-            addMapping((String) k.getKey(), (String) k.getValue());
+        for (String k: d.servletMapping.keySet()) {
+            addMapping(k, d.servletMapping.get(k));            
         }
         
         Iterator i5 = d.filterMappings.iterator();
@@ -1013,10 +1011,11 @@ public class ServletContextImpl implements ServletContext {
       addServletConfig(sc);
     }
     
-    public void addServlet(String servletName, Servlet servlet) {
+    public javax.servlet.Registration.Dynamic addServlet(String servletName, Servlet servlet) {
       ServletConfigImpl sc = new ServletConfigImpl(this, servletName, null);
       sc.setServlet(servlet);
       addServletConfig(sc);
+      return null;
     }
     
     public void addServletSec(String serlvetName, String runAs, Map roles) {
@@ -1375,54 +1374,75 @@ public class ServletContextImpl implements ServletContext {
    }
 
    @Override
-   public void addFilter(String filterName, String description, String className,
-                         Map<String, String> initParameters,
-                         boolean isAsyncSupported) {
+   public EnumSet<SessionTrackingMode> getDefaultSessionTrackingModes() {
+       return null;
    }
 
    @Override
-   public void addFilterMappingForServletNames(
-                                               String filterName,
-                                               EnumSet<DispatcherType> dispatcherTypes,
-                                               boolean isMatchAfter,
-                                               String... servletNames) {
+   public EnumSet<SessionTrackingMode> getEffectiveSessionTrackingModes() {
+       return null;
    }
 
    @Override
-   public void addFilterMappingForUrlPatterns(
-                                              String filterName,
-                                              EnumSet<DispatcherType> dispatcherTypes,
-                                              boolean isMatchAfter,
-                                              String... urlPatterns) {
+   public SessionCookieConfig getSessionCookieConfig() {
+       return null;
    }
 
    @Override
-   public void addServletMapping(String servletName, String[] urlPatterns) {
+   public void setSessionTrackingModes(EnumSet<SessionTrackingMode> sessionTrackingModes) {
    }
 
    @Override
-   public EnumSet<SessionTrackingMode> getDefaultSessionTrackingModes() {
+   public Dynamic addFilter(String filterName, String className) {
        return null;
    }
 
    @Override
-   public EnumSet<SessionTrackingMode> getEffectiveSessionTrackingModes() {
+   public Dynamic addFilter(String filterName, Filter filter) {
        return null;
    }
 
    @Override
-   public SessionCookieConfig getSessionCookieConfig() {
+   public Dynamic addFilter(String filterName, Class<? extends Filter> filterClass) {
        return null;
    }
 
    @Override
-   public void setSessionCookieConfig(SessionCookieConfig sessionCookieConfig) {
+   public javax.servlet.Registration.Dynamic addServlet(String servletName,
+                                                        String className) {
+       return null;
    }
 
    @Override
-   public void setSessionTrackingModes(
-                                       EnumSet<SessionTrackingMode> sessionTrackingModes) {
+   public javax.servlet.Registration.Dynamic addServlet(
+                                                        String servletName,
+                                                        Class<? extends Servlet> servletClass) {
+       return null;
+   }
+
+   @Override
+   public <T extends Filter> T createFilter(Class<T> c) throws ServletException {
+       return null;
    }
 
+   @Override
+   public <T extends Servlet> T createServlet(Class<T> c) throws ServletException {
+       return null;
+   }
+
+   @Override
+   public FilterRegistration findFilterRegistration(String filterName) {
+       return null;
+   }
+
+   @Override
+   public ServletRegistration findServletRegistration(String servletName) {
+       return null;
+   }
+
+   @Override
+   public boolean setInitParameter(String name, String value) {
+       return false;
+   }
 }
 
index 2cd699c..53ae9d0 100644 (file)
@@ -21,7 +21,6 @@ import java.io.IOException;
 
 import javax.servlet.ServletOutputStream;
 
-import org.apache.tomcat.lite.coyote.MessageWriter;
 
 /**
  * Coyote implementation of the servlet output stream.
@@ -36,13 +35,13 @@ public class ServletOutputStreamImpl
     // ----------------------------------------------------- Instance Variables
 
 
-    protected MessageWriter ob;
+    protected BodyWriter ob;
 
 
     // ----------------------------------------------------------- Constructors
 
 
-    public ServletOutputStreamImpl(MessageWriter ob) {
+    public ServletOutputStreamImpl(BodyWriter ob) {
         this.ob = ob;
     }
 
index 0cd9cd4..644c460 100644 (file)
@@ -36,8 +36,10 @@ import java.util.logging.Level;
 import javax.security.auth.Subject;
 import javax.servlet.AsyncContext;
 import javax.servlet.AsyncListener;
+import javax.servlet.DispatcherType;
 import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
 import javax.servlet.ServletInputStream;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletRequestAttributeEvent;
@@ -45,12 +47,11 @@ import javax.servlet.ServletRequestAttributeListener;
 import javax.servlet.ServletResponse;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
+import javax.servlet.http.Part;
 
-import org.apache.coyote.ActionCode;
-import org.apache.coyote.Request;
 import org.apache.tomcat.addons.UserSessionManager;
-import org.apache.tomcat.lite.coyote.MessageReader;
 import org.apache.tomcat.servlets.util.Enumerator;
 import org.apache.tomcat.servlets.util.LocaleParser;
 import org.apache.tomcat.servlets.util.RequestUtil;
@@ -60,19 +61,19 @@ import org.apache.tomcat.util.buf.MessageBytes;
 import org.apache.tomcat.util.buf.UriNormalizer;
 import org.apache.tomcat.util.http.Cookies;
 import org.apache.tomcat.util.http.FastHttpDateFormat;
+import org.apache.tomcat.util.http.HttpRequest;
 import org.apache.tomcat.util.http.Parameters;
 import org.apache.tomcat.util.http.ServerCookie;
 import org.apache.tomcat.util.http.mapper.MappingData;
 
 
 /**
+ * 
  * Wrapper object for the Coyote request.
  *
  * @author Remy Maucherat
  * @author Craig R. McClanahan
- * @version $Revision$ $Date$
  */
-
 public class ServletRequestImpl implements HttpServletRequest {
 
     /**
@@ -287,21 +288,21 @@ public class ServletRequestImpl implements HttpServletRequest {
     /**
      * The associated input buffer.
      */
-    protected MessageReader inputBuffer = new MessageReader();
+    protected BodyReader inputBuffer;
 
+    Connector connector;
 
     /**
      * ServletInputStream.
      */
-    protected ServletInputStreamImpl inputStream = 
-        new ServletInputStreamImpl(inputBuffer.asInputStream());
+    protected ServletInputStreamImpl inputStream; 
 
 
     /**
      * Reader.
      */
-    protected BufferedReader reader = new ServletReaderImpl(inputBuffer);
-
+    protected BufferedReader reader;
+    
 
     /**
      * Using stream flag.
@@ -426,7 +427,7 @@ public class ServletRequestImpl implements HttpServletRequest {
     public  byte[] postData = null;
 
     
-    private Request coyoteRequest;
+    private HttpRequest httpRequest;
     
     /** New IO/buffer model  
      */
@@ -495,6 +496,13 @@ public class ServletRequestImpl implements HttpServletRequest {
         // Not used
     }
 
+    public void setConnector(Connector c) {
+        connector = c;
+    }
+    
+    public Connector getConnector() {
+        return connector;
+    }
 
     /**
      * Add a Locale to the set of preferred Locales for this Request.  The
@@ -516,7 +524,7 @@ public class ServletRequestImpl implements HttpServletRequest {
      * @param values Corresponding values for this request parameter
      */
     public void addParameter(String name, String values[]) {
-        coyoteRequest.getParameters().addParameterValues(name, values);
+        httpRequest.getParameters().addParameterValues(name, values);
     }
 
     /**
@@ -648,7 +656,7 @@ public class ServletRequestImpl implements HttpServletRequest {
      * Return the character encoding for this Request.
      */
     public String getCharacterEncoding() {
-      return (coyoteRequest.getCharacterEncoding());
+      return (httpRequest.getCharacterEncoding());
     }
 
 
@@ -656,7 +664,7 @@ public class ServletRequestImpl implements HttpServletRequest {
      * Return the content length for this Request.
      */
     public int getContentLength() {
-        return (coyoteRequest.getContentLength());
+        return (httpRequest.getContentLength());
     }
 
 
@@ -707,7 +715,7 @@ public class ServletRequestImpl implements HttpServletRequest {
      * Return the content type for this Request.
      */
     public String getContentType() {
-        return (coyoteRequest.getContentType());
+        return (httpRequest.getContentType());
     }
 
 
@@ -792,7 +800,7 @@ public class ServletRequestImpl implements HttpServletRequest {
      * @return the URL decoded request URI
      */
     public String getDecodedRequestURI() {
-        return (coyoteRequest.decodedURI().toString());
+        return (httpRequest.decodedURI().toString());
     }
 
 
@@ -802,7 +810,7 @@ public class ServletRequestImpl implements HttpServletRequest {
      * @return the URL decoded request URI
      */
     public MessageBytes getDecodedRequestURIMB() {
-        return (coyoteRequest.decodedURI());
+        return (httpRequest.decodedURI());
     }
 
 
@@ -823,14 +831,14 @@ public class ServletRequestImpl implements HttpServletRequest {
      * @param name Name of the requested header
      */
     public String getHeader(String name) {
-        return coyoteRequest.getHeader(name);
+        return httpRequest.getHeader(name);
     }
     
     /**
      * Return the names of all headers received with this request.
      */
     public Enumeration getHeaderNames() {
-        return coyoteRequest.getMimeHeaders().names();
+        return httpRequest.getMimeHeaders().names();
     }
 
 
@@ -841,7 +849,7 @@ public class ServletRequestImpl implements HttpServletRequest {
      * @param name Name of the requested header
      */
     public Enumeration getHeaders(String name) {
-        return coyoteRequest.getMimeHeaders().values(name);
+        return httpRequest.getMimeHeaders().values(name);
     }
 
     /**
@@ -891,7 +899,7 @@ public class ServletRequestImpl implements HttpServletRequest {
      * which the request  was received.
      */       
     public String getLocalAddr(){
-        return coyoteRequest.localAddr().toString();
+        return httpRequest.localAddr().toString();
     }
 
 
@@ -940,7 +948,7 @@ public class ServletRequestImpl implements HttpServletRequest {
      * which the request was received.
      */
     public String getLocalName(){
-        return coyoteRequest.localName().toString();
+        return httpRequest.localName().toString();
     }
 
 
@@ -949,7 +957,7 @@ public class ServletRequestImpl implements HttpServletRequest {
      * on which the request was received.
      */
     public int getLocalPort(){
-        return coyoteRequest.getLocalPort();
+        return httpRequest.getLocalPort();
     }
 
 
@@ -966,7 +974,7 @@ public class ServletRequestImpl implements HttpServletRequest {
      * Return the HTTP request method used in this Request.
      */
     public String getMethod() {
-        return coyoteRequest.method().toString();
+        return httpRequest.method().toString();
     }
 
 
@@ -982,7 +990,7 @@ public class ServletRequestImpl implements HttpServletRequest {
         if (!parametersParsed)
             parseParameters();
 
-        return coyoteRequest.getParameters().getParameter(name);
+        return httpRequest.getParameters().getParameter(name);
 
     }
 
@@ -1023,7 +1031,7 @@ public class ServletRequestImpl implements HttpServletRequest {
         if (!parametersParsed)
             parseParameters();
 
-        return coyoteRequest.getParameters().getParameterNames();
+        return httpRequest.getParameters().getParameterNames();
 
     }
 
@@ -1039,7 +1047,7 @@ public class ServletRequestImpl implements HttpServletRequest {
         if (!parametersParsed)
             parseParameters();
 
-        return coyoteRequest.getParameters().getParameterValues(name);
+        return httpRequest.getParameters().getParameterValues(name);
 
     }
 
@@ -1090,14 +1098,14 @@ public class ServletRequestImpl implements HttpServletRequest {
      * Return the protocol and version used to make this Request.
      */
     public String getProtocol() {
-        return coyoteRequest.protocol().toString();
+        return httpRequest.protocol().toString();
     }
 
     /**
      * Return the query string associated with this request.
      */
     public String getQueryString() {
-        String queryString = coyoteRequest.queryString().toString();
+        String queryString = httpRequest.queryString().toString();
         if (queryString == null || queryString.equals("")) {
             return (null);
         } else {
@@ -1184,10 +1192,10 @@ public class ServletRequestImpl implements HttpServletRequest {
      * Return the remote IP address making this Request.
      */
     public String getRemoteAddr() {
-      if (coyoteRequest.remoteAddr().isNull()) {
-        coyoteRequest.action(ActionCode.ACTION_REQ_HOST_ADDR_ATTRIBUTE, coyoteRequest);
+      if (httpRequest.remoteAddr().isNull()) {
+        httpRequest.remoteAddr().setString(connector.getRemoteAddr(this));
       }
-      return coyoteRequest.remoteAddr().toString();
+      return httpRequest.remoteAddr().toString();
     }
 
 
@@ -1195,10 +1203,10 @@ public class ServletRequestImpl implements HttpServletRequest {
      * Return the remote host name making this Request.
      */
     public String getRemoteHost() {
-      if (coyoteRequest.remoteHost().isNull()) {
-        coyoteRequest.action(ActionCode.ACTION_REQ_HOST_ATTRIBUTE, coyoteRequest);
+      if (httpRequest.remoteHost().isNull()) {
+        httpRequest.remoteHost().setString(connector.getRemoteHost(this));
       }
-      return coyoteRequest.remoteHost().toString();
+      return httpRequest.remoteHost().toString();
     }
 
 
@@ -1207,7 +1215,7 @@ public class ServletRequestImpl implements HttpServletRequest {
      * or last proxy that sent the request.
      */    
     public int getRemotePort(){
-        return coyoteRequest.getRemotePort();
+        return httpRequest.getRemotePort();
     }
 
 
@@ -1234,15 +1242,20 @@ public class ServletRequestImpl implements HttpServletRequest {
         return this;
     }
     
-    public Request getCoyoteRequest() {
-      return coyoteRequest;
+    public HttpRequest getHttpRequest() {
+      return httpRequest;
     }
     
-    public void setCoyoteRequest(Request req) {
-      this.coyoteRequest = req;
-      inputBuffer.setRequest(req);
+    public void setHttpRequest(HttpRequest req, BodyReader in) {
+      this.httpRequest = req;
+      inputBuffer = in;
+      inputStream = new ServletInputStreamImpl(inputBuffer.asInputStream());
+      reader = new ServletReaderImpl(inputBuffer);
     }
 
+    public BodyReader getBodyReader() {
+        return inputBuffer;
+    }
 
     /**
      * Return a RequestDispatcher that wraps the resource at the specified
@@ -1315,16 +1328,16 @@ public class ServletRequestImpl implements HttpServletRequest {
      * Return the request URI for this request.
      */
     public String getRequestURI() {
-        return coyoteRequest.requestURI().toString();
+        return httpRequest.requestURI().toString();
     }
     
     /**
      */
     public void setRequestURI(String uri) {
-      coyoteRequest.decodedURI().setString(uri);
+      httpRequest.decodedURI().setString(uri);
       try {
-        UriNormalizer.decodeRequest(coyoteRequest.decodedURI(), 
-                coyoteRequest.requestURI(), coyoteRequest.getURLDecoder());
+        UriNormalizer.decodeRequest(httpRequest.decodedURI(), 
+                httpRequest.requestURI(), httpRequest.getURLDecoder());
       } catch(IOException ioe) {
         ioe.printStackTrace();
         return;
@@ -1384,7 +1397,7 @@ public class ServletRequestImpl implements HttpServletRequest {
      * Return the scheme used to make this Request.
      */
     public String getScheme() {
-        String scheme = coyoteRequest.scheme().toString();
+        String scheme = httpRequest.scheme().toString();
         if (scheme == null) {
             scheme = (isSecure() ? "https" : "http");
         }
@@ -1396,7 +1409,7 @@ public class ServletRequestImpl implements HttpServletRequest {
      * Return the server name responding to this Request.
      */
     public String getServerName() {
-        return (coyoteRequest.serverName().toString());
+        return (httpRequest.serverName().toString());
     }
 
 
@@ -1404,7 +1417,7 @@ public class ServletRequestImpl implements HttpServletRequest {
      * Return the server port responding to this Request.
      */
     public int getServerPort() {
-        return (coyoteRequest.getServerPort());
+        return (httpRequest.getServerPort());
     }
 
 
@@ -1600,7 +1613,7 @@ public class ServletRequestImpl implements HttpServletRequest {
         parameterMap.clear();
 
         mappingData.recycle();
-
+        httpRequest.recycle();
     }
 
 
@@ -1772,7 +1785,7 @@ public class ServletRequestImpl implements HttpServletRequest {
         String dummy = new String(buffer, enc);
 
         // Save the validated encoding
-        coyoteRequest.setCharacterEncoding(enc);
+        httpRequest.setCharacterEncoding(enc);
 
     }
 
@@ -1863,7 +1876,7 @@ public class ServletRequestImpl implements HttpServletRequest {
      * @param method The request method
      */
     public void setMethod(String method) {
-      coyoteRequest.method().setString(method);
+      httpRequest.method().setString(method);
     }
 
 
@@ -1990,7 +2003,7 @@ public class ServletRequestImpl implements HttpServletRequest {
      * @param name The server name
      */
     public void setServerName(String name) {
-        coyoteRequest.serverName().setString(name);
+        httpRequest.serverName().setString(name);
     }
 
 
@@ -2000,7 +2013,7 @@ public class ServletRequestImpl implements HttpServletRequest {
      * @param port The server port
      */
     public void setServerPort(int port) {
-        coyoteRequest.setServerPort(port);
+        httpRequest.setServerPort(port);
     }
 
 
@@ -2067,7 +2080,7 @@ public class ServletRequestImpl implements HttpServletRequest {
 
 
     public String toString() {
-        return coyoteRequest.requestURI().toString();
+        return httpRequest.requestURI().toString();
     }
 
 
@@ -2195,7 +2208,7 @@ public class ServletRequestImpl implements HttpServletRequest {
 
         cookiesParsed = true;
 
-        Cookies serverCookies = coyoteRequest.getCookies();
+        Cookies serverCookies = httpRequest.getCookies();
         int count = serverCookies.getCookieCount();
         if (count <= 0)
             return;
@@ -2271,7 +2284,7 @@ public class ServletRequestImpl implements HttpServletRequest {
 
         parametersParsed = true;
 
-        Parameters parameters = coyoteRequest.getParameters();
+        Parameters parameters = httpRequest.getParameters();
 
         // getCharacterEncoding() may have been overridden to search for
         // hidden form field containing request encoding
@@ -2349,7 +2362,7 @@ public class ServletRequestImpl implements HttpServletRequest {
         String sessionCookieName = context.getSessionCookieName();
         
         // Parse session id from cookies
-        Cookies serverCookies = coyoteRequest.getCookies();
+        Cookies serverCookies = httpRequest.getCookies();
         int count = serverCookies.getCookieCount();
         if (count <= 0)
             return;
@@ -2382,9 +2395,8 @@ public class ServletRequestImpl implements HttpServletRequest {
      * Parse session id in URL.
      */
     protected void parseSessionId() {
-        Request req = coyoteRequest;
         ServletRequestImpl request = this;
-        ByteChunk uriBC = req.requestURI().getByteChunk();
+        ByteChunk uriBC = httpRequest.requestURI().getByteChunk();
         int semicolon = uriBC.indexOf(match, 0, match.length(), 0);
 
         if (semicolon > 0) {
@@ -2507,4 +2519,45 @@ public class ServletRequestImpl implements HttpServletRequest {
     }
 
 
+    @Override
+    public boolean authenticate(HttpServletResponse response)
+            throws IOException, ServletException {
+        return false;
+    }
+
+
+    @Override
+    public Part getPart(String name) {
+        return null;
+    }
+
+
+    @Override
+    public Iterable<Part> getParts() {
+        return null;
+    }
+
+
+    @Override
+    public void login(String username, String password) throws ServletException {
+    }
+
+
+    @Override
+    public void logout() throws ServletException {
+    }
+
+
+    @Override
+    public long getAsyncTimeout() {
+        return 0;
+    }
+
+
+    @Override
+    public DispatcherType getDispatcherType() {
+        return null;
+    }
+
+
 }
index 4114d19..0ae93b1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
+ * ontentLicensed 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
@@ -34,12 +34,11 @@ import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
-import org.apache.coyote.Response;
-import org.apache.tomcat.lite.coyote.MessageWriter;
 import org.apache.tomcat.util.buf.CharChunk;
 import org.apache.tomcat.util.buf.MessageBytes;
 import org.apache.tomcat.util.buf.UEncoder;
 import org.apache.tomcat.util.http.FastHttpDateFormat;
+import org.apache.tomcat.util.http.HttpResponse;
 import org.apache.tomcat.util.http.MimeHeaders;
 import org.apache.tomcat.util.http.ServerCookie;
 
@@ -62,56 +61,23 @@ public class ServletResponseImpl
         "EEE, dd MMM yyyy HH:mm:ss zzz";
 
     // ----------------------------------------------------------- Constructors
-
-    private Response resB;
+    
     
     ServletResponseImpl() {
         urlEncoder.addSafeCharacter('/');
     }
 
 
-    // ----------------------------------------------------- Class Variables
-
-
-    /**
-     * Descriptive information about this Response implementation.
-     */
-    protected static final String info =
-        "org.apache.tomcat.lite/1.0";
-
-
-    // ----------------------------------------------------- Instance Variables
-
     /**
      * The date format we will use for creating date headers.
      */
     protected SimpleDateFormat format = null;
 
 
-    // ------------------------------------------------------------- Properties
-
-
-    /**
-     * Set the Connector through which this Request was received.
-     *
-     * @param connector The new connector
-     */
-    public void setConnector() {
-        // default size to size of one ajp-packet
-        outputBuffer = MessageWriter.getWriter(req.getCoyoteRequest(), getCoyoteResponse(), 4096);
-        outputStream = new ServletOutputStreamImpl(outputBuffer);
-    }
-
-    /**
-     * Coyote response.
-     */
-    //protected org.apache.coyote.Response coyoteResponse;
-
-
     /**
      * The associated output buffer.
      */
-    protected MessageWriter outputBuffer;
+    protected BodyWriter outputBuffer;
 
 
     /**
@@ -168,6 +134,11 @@ public class ServletResponseImpl
 
 
     /**
+     * The request with which this response is associated.
+     */
+    protected ServletRequestImpl req = null;
+
+    /**
      * URL encoder.
      */
     protected UEncoder urlEncoder = new UEncoder();
@@ -179,6 +150,27 @@ public class ServletResponseImpl
     protected CharChunk redirectURLCC = new CharChunk(1024);
 
 
+    private HttpResponse resB;
+    
+    
+    // Cached/derived information - reflected in headers
+    protected static Locale DEFAULT_LOCALE = Locale.getDefault();
+    
+    public static final String DEFAULT_CHARACTER_ENCODING="ISO-8859-1";
+
+    protected Locale locale = DEFAULT_LOCALE;
+
+    // XXX 
+    protected boolean commited = false;
+    protected String contentType = null;
+    
+    /**
+     * Has the charset been explicitly set.
+     */
+    protected boolean charsetSet = false;
+    protected String characterEncoding = DEFAULT_CHARACTER_ENCODING;
+
+
     // --------------------------------------------------------- Public Methods
 
 
@@ -188,10 +180,10 @@ public class ServletResponseImpl
      */
     public void recycle() {
 
-        outputBuffer.recycle();
         usingOutputStream = false;
         usingWriter = false;
         appCommitted = false;
+        commited = false;
         included = false;
         error = false;
         isCharacterEncodingSet = false;
@@ -199,7 +191,8 @@ public class ServletResponseImpl
         cookies.clear();
 
         outputBuffer.recycle();
-
+        
+        resB.recycle();
     }
 
 
@@ -210,7 +203,7 @@ public class ServletResponseImpl
      * Return the number of bytes actually written to the output stream.
      */
     public int getContentCount() {
-        return outputBuffer.getContentWritten();
+        return outputBuffer.getBytesWritten() + outputBuffer.getCharsWritten();
     }
 
 
@@ -229,8 +222,8 @@ public class ServletResponseImpl
      */
     public boolean isAppCommitted() {
         return (this.appCommitted || isCommitted() || isSuspended()
-                || ((getContentLength() > 0) 
-                    && (getContentCount() >= getContentLength())));
+                || ((getHttpResponse().getContentLength() > 0) 
+                    && (getContentCount() >= getHttpResponse().getContentLength())));
     }
 
 
@@ -254,21 +247,6 @@ public class ServletResponseImpl
 
 
     /**
-     * Return descriptive information about this Response implementation and
-     * the corresponding version number, in the format
-     * <code>&lt;description&gt;/&lt;version&gt;</code>.
-     */
-    public String getInfo() {
-        return (info);
-    }
-
-
-    /**
-     * The request with which this response is associated.
-     */
-    protected ServletRequestImpl req = null;
-
-    /**
      * Return the Request with which this Response is associated.
      */
     public ServletRequestImpl getRequest() {
@@ -289,9 +267,6 @@ public class ServletResponseImpl
      * Return the output stream associated with this Response.
      */
     public OutputStream getStream() {
-        if (outputStream == null) {
-            outputStream = new ServletOutputStreamImpl(outputBuffer);
-        }
         return outputStream;
     }
 
@@ -351,27 +326,23 @@ public class ServletResponseImpl
     public ServletOutputStream createOutputStream() 
         throws IOException {
         // Probably useless
-        if (outputStream == null) {
-            outputStream = new ServletOutputStreamImpl(outputBuffer);
-        }
         return outputStream;
     }
 
-
-    /**
-     * Return the content length that was set or calculated for this Response.
-     */
-    public int getContentLength() {
-        return getCoyoteResponse().getContentLength();
-    }
-
-
     /**
      * Return the content type that was set or calculated for this response,
      * or <code>null</code> if no content type was set.
      */
     public String getContentType() {
-        return getCoyoteResponse().getContentType();
+        String ret = contentType;
+
+        if (ret != null 
+            && characterEncoding != null
+            && charsetSet) {
+            ret = ret + ";charset=" + characterEncoding;
+        }
+
+        return ret;
     }
 
 
@@ -426,7 +397,7 @@ public class ServletResponseImpl
      * Return the character encoding used for this Response.
      */
     public String getCharacterEncoding() {
-        return (getCoyoteResponse().getCharacterEncoding());
+        return characterEncoding;
     }
 
 
@@ -445,19 +416,19 @@ public class ServletResponseImpl
                 ("usingWriter");
 
         usingOutputStream = true;
-        if (outputStream == null) {
-            outputStream = new ServletOutputStreamImpl(outputBuffer);
-        }
         return outputStream;
 
     }
 
+    public BodyWriter getBodyWriter() {
+        return outputBuffer;
+    }
 
     /**
      * Return the Locale assigned to this response.
      */
     public Locale getLocale() {
-        return (getCoyoteResponse().getLocale());
+        return locale;
     }
 
 
@@ -503,10 +474,9 @@ public class ServletResponseImpl
      * Has the output of this response already been committed?
      */
     public boolean isCommitted() {
-        return (getCoyoteResponse().isCommitted());
+        return getHttpResponse().isCommitted();
     }
 
-
     /**
      * Clear any content written to the buffer.
      *
@@ -518,8 +488,16 @@ public class ServletResponseImpl
         if (included)
             return;     // Ignore any call from an included servlet
 
-        getCoyoteResponse().reset();
-        //req.con.reset();
+        if (isCommitted())
+            throw new IllegalStateException("isCommitted");
+        
+        resB.recycle(); // reset headers, status code, message
+        req.getConnector().reset(this);
+        contentType = null;
+        locale = DEFAULT_LOCALE;
+        characterEncoding = DEFAULT_CHARACTER_ENCODING;
+        charsetSet = false;
+        
         outputBuffer.reset();
     }
 
@@ -577,7 +555,7 @@ public class ServletResponseImpl
         if (usingWriter && !"ISO-8859-1".equals(getCharacterEncoding())) {
             return;
         }
-        getCoyoteResponse().setContentLength(length);
+        getHttpResponse().setContentLength(length);
 
     }
 
@@ -606,7 +584,7 @@ public class ServletResponseImpl
             }
         }
 
-        getCoyoteResponse().setContentType(type);
+        getHttpResponse().setContentType(type);
 
         // Check to see if content type contains charset
         if (type != null) {
@@ -654,7 +632,13 @@ public class ServletResponseImpl
         if (usingWriter)
             return;
 
-        getCoyoteResponse().setCharacterEncoding(charset);
+        if (isCommitted())
+            return;
+        if (charset == null)
+            return;
+
+        characterEncoding = charset;
+        charsetSet=true;
         isCharacterEncodingSet = true;
     }
 
@@ -675,7 +659,25 @@ public class ServletResponseImpl
         if (included)
             return;
 
-        getCoyoteResponse().setLocale(locale);
+        if (locale == null) {
+            return;  // throw an exception?
+        }
+
+        // Save the locale for use by getLocale()
+        this.locale = locale;
+
+        // Set the contentLanguage for header output
+        String contentLanguage = locale.getLanguage();
+        if ((contentLanguage != null) && (contentLanguage.length() > 0)) {
+            String country = locale.getCountry();
+            StringBuffer value = new StringBuffer(contentLanguage);
+            if ((country != null) && (country.length() > 0)) {
+                value.append('-');
+                value.append(country);
+            }
+            contentLanguage = value.toString();
+        }
+        resB.setHeader("Content-Language", contentLanguage);
 
         // Ignore any call made after the getWriter has been invoked.
         // The default should be used
@@ -689,7 +691,7 @@ public class ServletResponseImpl
         Locale2Charset cm = req.getContext().getCharsetMapper();
         String charset = cm.getCharset( locale );
         if ( charset != null ){
-            getCoyoteResponse().setCharacterEncoding(charset);
+            setCharacterEncoding(charset);
         }
 
     }
@@ -716,7 +718,7 @@ public class ServletResponseImpl
      * @param name Header name to look up
      */
     public String getHeader(String name) {
-        return getCoyoteResponse().getMimeHeaders().getHeader(name);
+        return getHttpResponse().getMimeHeaders().getHeader(name);
     }
 
 
@@ -724,16 +726,15 @@ public class ServletResponseImpl
      * Return an array of all the header names set for this response, or
      * a zero-length array if no headers have been set.
      */
-    public String[] getHeaderNames() {
+    public Iterable<String> getHeaderNames() {
 
-        MimeHeaders headers = getCoyoteResponse().getMimeHeaders();
+        MimeHeaders headers = getHttpResponse().getMimeHeaders();
         int n = headers.size();
-        String[] result = new String[n];
+        ArrayList<String> result = new ArrayList<String>();
         for (int i = 0; i < n; i++) {
-            result[i] = headers.getName(i).toString();
+            result.add(headers.getName(i).toString());
         }
         return result;
-
     }
 
 
@@ -746,7 +747,7 @@ public class ServletResponseImpl
      */
     public String[] getHeaderValues(String name) {
 
-        Enumeration enumeration = getCoyoteResponse().getMimeHeaders().values(name);
+        Enumeration enumeration = getHttpResponse().getMimeHeaders().values(name);
         Vector result = new Vector();
         while (enumeration.hasMoreElements()) {
             result.addElement(enumeration.nextElement());
@@ -763,7 +764,7 @@ public class ServletResponseImpl
      * for this Response.
      */
     public String getMessage() {
-        return getCoyoteResponse().getMessage();
+        return getHttpResponse().getMessage();
     }
 
 
@@ -771,7 +772,7 @@ public class ServletResponseImpl
      * Return the HTTP status code associated with this Response.
      */
     public int getStatus() {
-        return getCoyoteResponse().getStatus();
+        return getHttpResponse().getStatus();
     }
 
 
@@ -864,7 +865,7 @@ public class ServletResponseImpl
         if (included)
             return;
 
-        getCoyoteResponse().addHeader(name, value);
+        getHttpResponse().addHeader(name, value);
 
     }
 
@@ -901,15 +902,15 @@ public class ServletResponseImpl
         if(cc=='C' || cc=='c') {
             if(name.equalsIgnoreCase("Content-Type")) {
                 // Will return null if this has not been set
-                return (getCoyoteResponse().getContentType() != null);
+                return getContentType() != null;
             }
             if(name.equalsIgnoreCase("Content-Length")) {
                 // -1 means not known and is not sent to client
-                return (getCoyoteResponse().getContentLengthLong() != -1);
+                return (getHttpResponse().getContentLength() != -1);
             }
         }
 
-        return getCoyoteResponse().containsHeader(name);
+        return getHttpResponse().containsHeader(name);
     }
 
 
@@ -995,8 +996,7 @@ public class ServletResponseImpl
         if (included)
             return; 
 
-        getCoyoteResponse().acknowledge();
-
+        req.getConnector().acknowledge(this);
     }
 
 
@@ -1039,8 +1039,8 @@ public class ServletResponseImpl
 
         setError();
 
-        getCoyoteResponse().setStatus(status);
-        getCoyoteResponse().setMessage(message);
+        getHttpResponse().setStatus(status);
+        getHttpResponse().setMessage(message);
 
         // Clear any data content that has been buffered
         resetBuffer();
@@ -1156,7 +1156,7 @@ public class ServletResponseImpl
         if (included)
             return;
 
-        getCoyoteResponse().setHeader(name, value);
+        getHttpResponse().setHeader(name, value);
 
     }
 
@@ -1210,8 +1210,8 @@ public class ServletResponseImpl
         if (included)
             return;
 
-        getCoyoteResponse().setStatus(status);
-        getCoyoteResponse().setMessage(message);
+        getHttpResponse().setStatus(status);
+        getHttpResponse().setMessage(message);
 
     }
 
@@ -1425,23 +1425,35 @@ public class ServletResponseImpl
       return outputBuffer.getBytesWritten();
     }
 
-    public MessageWriter getOutputBuffer() {
+    public BodyWriter getOutputBuffer() {
       return outputBuffer;
     }
+    
+    public void setWriter(BodyWriter ob) {
+        outputBuffer = ob;
+        outputStream = new ServletOutputStreamImpl(outputBuffer);
+    }
 
     public CharSequence getResponseHeader(String name) {
-      MessageBytes v = getCoyoteResponse().getMimeHeaders().getValue(name);
+      MessageBytes v = getHttpResponse().getMimeHeaders().getValue(name);
       return (v == null) ? null : v.toString();
     }
 
 
-    public Response getCoyoteResponse() {
+    public HttpResponse getHttpResponse() {
       return resB;
     }
 
 
-    public void setCoyoteResponse(Response resB) {
+    public void setHttpResponse(HttpResponse resB, BodyWriter ob) {
         this.resB = resB;
+        setWriter(ob);
+    }
+
+
+    @Override
+    public Iterable<String> getHeaders(String name) {
+        return null;
     }
 
 
index 5ddd9cd..b012205 100644 (file)
@@ -89,7 +89,7 @@ public class TomcatLite implements Runnable {
     
     Map<String,String> ctxDefaultInitParam = new HashMap();
         
-    Connector coyoteAdapter;
+    Connector connector;
     
     ObjectManager om;
     
@@ -106,7 +106,12 @@ public class TomcatLite implements Runnable {
     }
 
     // --------------- start/stop ---------------
-    
+
+    public static ObjectManager defaultObjectManager() {
+        SimpleObjectManager cfg = new SimpleObjectManager();
+        cfg.loadResource("org/apache/tomcat/lite/config.properties");
+        return cfg;
+    }
     /**
      * Return the object manager associated with this tomcat.
      * If none set, create a minimal one with the default 
@@ -114,12 +119,7 @@ public class TomcatLite implements Runnable {
      */
     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");
+            om = defaultObjectManager();
         }
         return om;
     }
@@ -223,7 +223,12 @@ public class TomcatLite implements Runnable {
                 e.printStackTrace();
             }
         }
-        stopConnector();
+        try {
+            stopConnector();
+        } catch (Exception e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
     }
 
     // -------------- Context add/remove --------------
@@ -309,9 +314,9 @@ public class TomcatLite implements Runnable {
         req.parseSessionId();
         
         try {
-          UriNormalizer.decodeRequest(req.getCoyoteRequest().decodedURI(), 
-                  req.getCoyoteRequest().requestURI(),
-                  req.getCoyoteRequest().getURLDecoder());
+          UriNormalizer.decodeRequest(req.getHttpRequest().decodedURI(), 
+                  req.getHttpRequest().requestURI(),
+                  req.getHttpRequest().getURLDecoder());
         } catch(IOException ioe) {
             res.setStatus(400);
             return;
@@ -336,7 +341,7 @@ public class TomcatLite implements Runnable {
           Thread.currentThread().setContextClassLoader(ctx.getClassLoader());
 
           WebappServletMapper mapper = ctx.getMapper();
-          mapper.map(req.getCoyoteRequest().decodedURI(), mapRes);
+          mapper.map(req.getHttpRequest().decodedURI(), mapRes);
 
           // Possible redirect
           MessageBytes redirectPathMB = mapRes.redirectPath;
@@ -548,8 +553,8 @@ public class TomcatLite implements Runnable {
       
       getConnector().initRequest(req, res);
       
-      req.getCoyoteRequest().method().setString("GET");
-      req.getCoyoteRequest().protocol().setString("HTTP/1.1");
+      req.getHttpRequest().method().setString("GET");
+      req.getHttpRequest().protocol().setString("HTTP/1.1");
       
       return req;
     }
@@ -585,42 +590,41 @@ public class TomcatLite implements Runnable {
     public void endRequest(ServletRequestImpl req,
                            ServletResponseImpl res) throws IOException {
      res.outputBuffer.flush();
-     res.getCoyoteResponse().finish();
+     req.getConnector().finishResponse(res);
     }
     
     public Connector getConnector() {
-        if (coyoteAdapter == null) {
-            coyoteAdapter = (Connector) getObjectManager().get(Connector.class);
-            setConnector(coyoteAdapter);
+        if (connector == null) {
+            connector = (Connector) getObjectManager().get(Connector.class);
+            setConnector(connector);
         }
-        return coyoteAdapter;
+        return connector;
     }
 
     public void setConnector(Connector c) {
-        coyoteAdapter = c;
-        coyoteAdapter.setTomcatLite(this);
-        getObjectManager().bind("Connector", coyoteAdapter);
+        connector = c;
+        connector.setTomcatLite(this);
+        getObjectManager().bind("Connector", connector);
     }
 
     
     public void setDaemon(boolean d) {
         getConnector();
-        if (coyoteAdapter != null) {
-            coyoteAdapter.setDaemon(d);
+        if (connector != null) {
+            connector.setDaemon(d);
         }
     }
 
-    public void startConnector() {
+    public void startConnector() throws IOException {
         getConnector();
-        if (coyoteAdapter != null) {
-            coyoteAdapter.start();
+        if (connector != null) {
+            connector.start();
         }
     }
 
-    public void stopConnector() {
-        getConnector();
-        if (coyoteAdapter != null) {
-            coyoteAdapter.stop();
+    public void stopConnector() throws Exception {
+        if (connector != null) {
+            connector.stop();
         }
     }
 
diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/cli/Main.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/cli/Main.java
deleted file mode 100644 (file)
index 3abe1f4..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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();
-  }    
-}
index c6e43e1..c1ef53d 100644 (file)
@@ -2,6 +2,10 @@
 # If tomcat is used with a proper framework, you need to bind and configure 
 # those objects in the framework. 
 
+Main.(class)=org.apache.tomcat.lite.TomcatLite
+
+Jmx.(class)=org.apache.tomcat.integration.jmx.JmxObjectManagerSpi
+
 # --- Class names for required plugin interfaces --- 
 
 org.apache.tomcat.lite.WebappServletMapper.(class)=org.apache.tomcat.lite.WebappServletMapper
@@ -13,16 +17,23 @@ org.apache.tomcat.addons.UserSessionManager.(class)=org.apache.tomcat.servlets.s
 # *.jsp support
 org.apache.tomcat.addons.UserTemplateClassMapper.(class)=org.apache.tomcat.servlets.jsp.JasperCompilerTemplateClassMapper
 
+org.apache.tomcat.addons.Filesystem.(class)=org.apache.tomcat.integration.simple.LocalFilesystem
+
 # 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
+org.apache.tomcat.lite.Connector.(class)=org.apache.tomcat.lite.coyote.CoyoteConnector
+
+# JMX 
+jmx-connector.(class)=org.apache.tomcat.integration.jmx.JmxObjectManagerSpi
 
 # --- 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
+filetemplate-servlet.(class)=org.apache.tomcat.servlets.jsp.JspFileTemplateServlet
+
 
diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/ClientAbortException.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/ClientAbortException.java
deleted file mode 100644 (file)
index 2155adf..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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$ $Date$
- */
-
-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());
-
-    }
-
-
-}
diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/CoyoteConnector.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/CoyoteConnector.java
new file mode 100644 (file)
index 0000000..88669e5
--- /dev/null
@@ -0,0 +1,465 @@
+/*
+ */
+package org.apache.tomcat.lite.coyote;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.coyote.ActionCode;
+import org.apache.coyote.ActionHook;
+import org.apache.coyote.Adapter;
+import org.apache.coyote.ProtocolHandler;
+import org.apache.coyote.Request;
+import org.apache.coyote.Response;
+import org.apache.coyote.http11.Http11NioProtocol;
+import org.apache.tomcat.integration.ObjectManager;
+import org.apache.tomcat.lite.BodyReader;
+import org.apache.tomcat.lite.BodyWriter;
+import org.apache.tomcat.lite.ClientAbortException;
+import org.apache.tomcat.lite.Connector;
+import org.apache.tomcat.lite.ServletRequestImpl;
+import org.apache.tomcat.lite.ServletResponseImpl;
+import org.apache.tomcat.lite.TomcatLite;
+import org.apache.tomcat.util.buf.ByteChunk;
+import org.apache.tomcat.util.buf.UriNormalizer;
+import org.apache.tomcat.util.http.HttpRequest;
+import org.apache.tomcat.util.http.HttpResponse;
+import org.apache.tomcat.util.net.SocketStatus;
+
+public class CoyoteConnector implements Adapter, Connector {
+
+    private TomcatLite lite;
+
+    public CoyoteConnector() {
+    }
+
+
+
+    public void acknowledge(HttpServletResponse res) throws IOException {
+        Response cres = (Response) ((ServletResponseImpl) res).getHttpResponse().nativeResponse;
+        cres.acknowledge();        
+    }
+
+    public void reset(HttpServletResponse res) {
+        Response cres = (Response) ((ServletResponseImpl) res).getHttpResponse().nativeResponse;
+        cres.reset();        
+    }
+    
+    public void recycle(HttpServletRequest req, HttpServletResponse res) {
+    
+    }
+    
+    public static HttpResponse getResponse(final Response cres) {
+        HttpResponse hres = new HttpResponse() {
+            public int getStatus() {
+                return cres.getStatus();
+            }
+            public void setStatus(int i) {
+                super.setStatus(i);
+                cres.setStatus(i);
+            }
+            public void setMessage(String s) {
+                super.setMessage(s);
+                cres.setMessage(s);
+            }
+            public String getMessage() {
+                return cres.getMessage();
+            }
+            public boolean isCommitted() {
+                return cres.isCommitted();
+            }
+
+            public void setCommitted(boolean b) {
+                cres.setCommitted(b);
+            }
+        };
+        
+        hres.setMimeHeaders(cres.getMimeHeaders());
+        hres.nativeResponse = cres;
+        
+        return hres;
+    }
+    
+    public static HttpRequest getRequest(Request req) {
+        
+        HttpRequest httpReq = new HttpRequest(req.scheme(),
+                req.method(), 
+                req.unparsedURI(),
+                req.protocol(),
+                req.getMimeHeaders(),
+                req.requestURI(),
+                req.decodedURI(),
+                req.query(), req.getParameters(),
+                req.serverName(), 
+                req.getCookies()) {
+            
+        };
+        httpReq.nativeRequest = req;
+        
+        // TODO: anything else computed in coyote ?
+        
+        return httpReq;
+    }
+
+    @Override
+    public void initRequest(HttpServletRequest hreq, HttpServletResponse hres) {
+        ServletRequestImpl req = (ServletRequestImpl) hreq;
+        ServletResponseImpl res = (ServletResponseImpl) hres;        
+        req.setConnector(this);
+        
+        Request creq = new Request();
+        Response cres = new Response();
+        HttpResponse nRes = getResponse(cres);
+
+        BodyWriter out = new BodyWriter(4096);
+        out.setConnector(this, res);
+        
+        res.setHttpResponse(nRes, out);
+        
+        cres.setRequest(creq);
+        cres.setHook(new ActionHook() {
+          public void action(ActionCode actionCode, 
+                             Object param) {
+          }
+        });
+        
+        BodyReader in = new BodyReader();
+        in.setConnector(this, req);
+        HttpRequest nReq = getRequest(creq);
+        req.setHttpRequest(nReq, in);
+        
+    }
+      
+
+    // ---- Coyote Adapter interface ---
+    
+    @Override
+    public void service(Request creq, Response cres) throws Exception {
+        long t0 = System.currentTimeMillis();
+
+        // compute decodedURI - not done by connector
+        UriNormalizer.decodeRequest(creq.decodedURI(), creq.requestURI(), creq.getURLDecoder());
+        
+        // find the facades
+        ServletRequestImpl req = (ServletRequestImpl) creq.getNote(ADAPTER_REQ_NOTE);
+        ServletResponseImpl res = (ServletResponseImpl) cres.getNote(ADAPTER_RES_NOTE);
+
+        
+        if (req == null) {
+          req = new ServletRequestImpl();
+          res = req.getResponse();
+          
+          BodyReader in = new BodyReader();
+          in.setConnector(this, req);
+
+          HttpRequest nReq = getRequest(creq);
+          nReq.setServerPort(creq.getServerPort());
+          HttpResponse nRes = getResponse(cres);
+          
+          req.setHttpRequest(nReq, in);
+          BodyWriter out = new BodyWriter(4096);
+          out.setConnector(this, res);
+          
+          res.setHttpResponse(nRes, out);
+          
+          creq.setNote(ADAPTER_REQ_NOTE, req);
+          cres.setNote(ADAPTER_RES_NOTE, res);
+          
+        }
+        req.setConnector(this);
+        
+        try {
+            lite.service(req, res);
+        } catch(IOException ex) {
+            throw ex;
+        } catch( Throwable t ) {
+            t.printStackTrace();
+        } finally {
+            long t1 = System.currentTimeMillis();
+            
+//            log.info("<<<<<<<< DONE: " + creq.method() + " " + 
+//                    creq.decodedURI() + " " + 
+//                    res.getStatus() + " " + 
+//                    (t1 - t0));
+            
+            // Final processing
+            // TODO: only if not commet, this doesn't work with the 
+            // other connectors since we don't have the info
+            // TODO: add this note in the nio/apr connectors
+            // TODO: play nice with TomcatLite, other adapters that flush/close
+            if (cres.getNote(COMET_RES_NOTE) == null) {
+
+                if (!res.isCommitted()) {
+                    cres.sendHeaders();
+                }
+                res.getOutputBuffer().flush();
+                
+                BodyWriter mw = res.getBodyWriter();
+                //MessageWriter.getWriter(creq, cres, 0);
+                mw.flush();
+                mw.recycle();
+
+                BodyReader reader = req.getBodyReader();
+                //getReader(creq);
+                reader.recycle();
+                
+                cres.finish();
+
+                creq.recycle();
+                cres.recycle();
+
+                req.recycle();
+                res.recycle();
+            }
+        }
+    }
+        
+    @Override
+    public boolean event(Request req, Response res, SocketStatus status)
+        throws Exception {
+      return false;
+    }
+
+
+    public void setTomcatLite(TomcatLite lite) {
+        this.lite = lite;
+    }
+
+
+    public String getRemoteHost(HttpServletRequest hreq) {
+        ServletRequestImpl req = (ServletRequestImpl) hreq;
+        
+        Request creq = (Request) req.getHttpRequest().nativeRequest;
+        creq.action(ActionCode.ACTION_REQ_HOST_ATTRIBUTE, creq);
+        return creq.remoteHost().toString();
+    }
+
+    public String getRemoteAddr(HttpServletRequest hreq) {
+        ServletRequestImpl req = (ServletRequestImpl) hreq;
+        
+        Request creq = (Request) req.getHttpRequest().nativeRequest;
+        creq.action(ActionCode.ACTION_REQ_HOST_ADDR_ATTRIBUTE, creq);
+        return creq.remoteAddr().toString();
+    }
+
+
+    @Override
+    public void beforeClose(HttpServletResponse res, int len) throws IOException {
+        Response cres = (Response) ((ServletResponseImpl) res).getHttpResponse().nativeResponse;
+    
+        if ((!cres.isCommitted()) 
+                && (cres.getContentLengthLong() == -1)) {
+                // Flushing the char buffer
+                // If this didn't cause a commit of the response, the final content
+                // length can be calculated
+                if (!cres.isCommitted()) {
+                    cres.setContentLength(len);
+                }
+            }
+    }
+
+    public int doRead(ServletRequestImpl hreq, ByteChunk bb) throws IOException {
+        ServletRequestImpl req = (ServletRequestImpl) hreq;
+        
+        Request creq = (Request) req.getHttpRequest().nativeRequest;
+        return creq.doRead(bb);
+    }
+
+    @Override
+    public void doWrite(HttpServletResponse res, ByteChunk chunk)
+            throws IOException {
+        Response cres = (Response) ((ServletResponseImpl) res).getHttpResponse().nativeResponse;
+        cres.doWrite(chunk);
+
+    }
+
+
+    @Override
+    public void realFlush(HttpServletResponse res) throws IOException {
+        Response cres = (Response) ((ServletResponseImpl) res).getHttpResponse().nativeResponse;
+        cres.action(ActionCode.ACTION_CLIENT_FLUSH, 
+                cres);
+        // If some exception occurred earlier, or if some IOE occurred
+        // here, notify the servlet with an IOE
+        if (cres.isExceptionPresent()) {
+            throw new ClientAbortException
+            (cres.getErrorException());
+        }
+
+    }
+
+
+    @Override
+    public void sendHeaders(HttpServletResponse res) throws IOException {
+        Response cres = (Response) ((ServletResponseImpl) res).getHttpResponse().nativeResponse;
+        
+        // This should happen before 'prepareResponse' is called !!
+        // Now update coyote response based on response
+        // don't set charset/locale - they're computed in lite
+        cres.setContentType(res.getContentType());
+        cres.sendHeaders();
+    }
+
+    @Override
+    public void finishResponse(HttpServletResponse res) throws IOException {
+        Response cres = (Response) ((ServletResponseImpl) res).getHttpResponse().nativeResponse;
+        cres.finish();
+    }
+
+    protected int port = 8800;
+    protected boolean daemon = false;
+
+    /**
+     * Note indicating the response is COMET. 
+     */
+    public static final int COMET_RES_NOTE = 2;
+    public static final int COMET_REQ_NOTE = 2;
+    
+    public static final int ADAPTER_RES_NOTE = 1;    
+    public static final int ADAPTER_REQ_NOTE = 1;    
+    
+    protected ProtocolHandler proto;
+
+    //protected Adapter adapter = new MapperAdapter();
+    protected int maxThreads = 20;
+    boolean started = false;
+    boolean async = false; // use old nio connector
+    
+    protected ObjectManager om;
+    
+    
+    public void setObjectManager(ObjectManager om) {
+        this.om = om;
+    }
+    
+    /** 
+     * Add an adapter. If more than the 'default' adapter is
+     * added, a MapperAdapter will be inserted.
+     * 
+     * @param path Use "/" for the default.
+     * @param adapter
+     */
+//    public void addAdapter(String path, Adapter added) {
+//        if ("/".equals(path)) {
+//            ((MapperAdapter) adapter).setDefaultAdapter(added);        
+//        } else {
+//            ((MapperAdapter) adapter).getMapper().addWrapper(path, added);
+//        }
+//    }
+    
+    /**
+     */
+    public void run() {
+        try {
+            init();
+            start();
+        } catch(IOException ex) {
+            ex.printStackTrace();
+        }
+    }
+
+    public void setDaemon(boolean b) {
+      daemon = b;
+    }
+    
+    protected void initAdapters() {
+        if (proto == null) {
+            addProtocolHandler(port, daemon);
+        }
+      // adapter = ...
+      // Adapter secondaryadapter = ...
+      //registry.registerComponent(secondaryadapter, ":name=adapter", null);
+    }
+
+    public void stop() throws Exception {
+      if (!started) {
+        return;
+      }
+      proto.destroy();
+      started = false;
+    }
+    
+//    /**
+//     *  Simple CLI support - arg is a path:className pair.
+//     */
+//    public void setAdapter(String arg)  {
+//      String[] pathClass = arg.split(":", 2);
+//      try {
+//        Class c = Class.forName(pathClass[1]);
+//        Adapter a = (Adapter) c.newInstance();
+//        addAdapter(pathClass[0],a);
+//      } catch (Throwable e) {
+//        e.printStackTrace();
+//      }
+//    }
+    
+    public void setConnector(ProtocolHandler h) {
+        this.proto = h;
+        h.setAttribute("port", Integer.toString(port));
+
+        om.bind("ProtocolHandler:" + "ep-" + port, proto);
+    }
+    
+    public void addProtocolHandler(int port, boolean daemon) {
+        Http11NioProtocol proto = new Http11NioProtocol();
+        proto.setCompression("on");
+        proto.setCompressionMinSize(32);
+        proto.setPort(port);
+        proto.getEndpoint().setDaemon(daemon);
+        setConnector(proto);
+        setPort(port);
+        setDaemon(daemon);
+    }
+    
+    public void addProtocolHandler(ProtocolHandler proto, 
+                                   int port, boolean daemon) {
+        setConnector(proto);
+        setPort(port);
+        setDaemon(daemon);
+    }
+    
+    public void setPort(int port) {
+        if (proto != null) {
+            proto.setAttribute("port", Integer.toString(port));
+        }
+        this.port = port;
+      }
+      
+    
+    public void init() {
+        //JdkLoggerConfig.loadCustom();
+        om.bind("CoyoteConnector:" + "CoyoteConnector-" + port, 
+                this);
+    }
+
+    
+    public void start() throws IOException {
+      try {
+        if (started) {
+          return;
+        }
+        init();
+        initAdapters();
+
+        // not required - should run fine without a connector.
+        if (proto != null) {
+            proto.setAdapter(this);
+        
+            proto.init();
+            proto.start();
+        }
+        
+        started = true;
+      } catch (Throwable e) {
+        e.printStackTrace();
+        throw new RuntimeException(e);
+      }
+    }
+    
+    public boolean getStarted() {
+      return started;
+    } 
+    
+}
diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/CoyoteHttp.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/CoyoteHttp.java
deleted file mode 100644 (file)
index 722eca1..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- */
-package org.apache.tomcat.lite.coyote;
-
-import java.io.IOException;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.coyote.ActionCode;
-import org.apache.coyote.ActionHook;
-import org.apache.coyote.Adapter;
-import org.apache.coyote.Request;
-import org.apache.coyote.Response;
-import org.apache.tomcat.integration.ObjectManager;
-import org.apache.tomcat.lite.Connector;
-import org.apache.tomcat.lite.ServletRequestImpl;
-import org.apache.tomcat.lite.ServletResponseImpl;
-import org.apache.tomcat.lite.TomcatLite;
-import org.apache.tomcat.util.net.SocketStatus;
-
-public class CoyoteHttp implements Adapter, Connector {
-
-    //private TomcatLite lite;
-    CoyoteServer coyote;
-    private TomcatLite lite;
-
-    public CoyoteHttp() {
-    }
-
-
-    @Override
-    public void finishResponse(HttpServletResponse res) throws IOException {
-        ((ServletResponseImpl) res).getCoyoteResponse().finish();
-    }
-
-
-    public void recycle(HttpServletRequest req, HttpServletResponse res) {
-    
-    }
-    
-    public void setPort(int port) {
-        if (getConnectors() != null) {
-            coyote.setPort(port);
-        }
-    }
-    
-    @Override
-    public void setDaemon(boolean b) {
-        if (getConnectors() != null) {
-            coyote.setDaemon(b);
-        }
-    }
-
-
-    @Override
-    public void start() {
-        if (getConnectors() != null) {
-            try {
-                coyote.init();
-                coyote.start();
-            } catch (Exception e) {
-                // TODO Auto-generated catch block
-                e.printStackTrace();
-            }
-        }
-    }
-
-
-
-    @Override
-    public void stop() {
-        if (coyote != null) {
-            try {
-                coyote.stop();
-            } catch (Exception e) {
-                // TODO Auto-generated catch block
-                e.printStackTrace();
-            }
-        }        
-    }
-    
-    @Override
-    public void initRequest(HttpServletRequest hreq, HttpServletResponse hres) {
-        ServletRequestImpl req = (ServletRequestImpl) hreq;
-        ServletResponseImpl res = (ServletResponseImpl) hres;
-        
-        Request creq = new Request();
-        res.setCoyoteResponse(new Response());
-        res.getCoyoteResponse().setRequest(creq);
-        res.getCoyoteResponse().setHook(new ActionHook() {
-          public void action(ActionCode actionCode, 
-                             Object param) {
-          }
-        });
-        
-        req.setCoyoteRequest(creq);
-        
-        res.setConnector();
-        
-    }
-      
-    // Coyote-specific hooking.
-    // This could be moved out to a separate class, TomcatLite can 
-    // work without it.
-    public CoyoteServer getConnectors() {
-        if (coyote == null) {
-            coyote = new CoyoteServer();
-            coyote.addAdapter("/", this);        
-        }
-        return coyote;
-    }
-
-    public void setConnectors(CoyoteServer server) {
-        this.coyote = server;
-        coyote.addAdapter("/", this);        
-    }
-
-    @Override
-    public void service(Request req, Response res) throws Exception {
-        // find the facades
-        ServletRequestImpl sreq = (ServletRequestImpl) req.getNote(CoyoteServer.ADAPTER_REQ_NOTE);
-        ServletResponseImpl sres = (ServletResponseImpl) res.getNote(CoyoteServer.ADAPTER_RES_NOTE);
-        if (sreq == null) {
-          sreq = new ServletRequestImpl();
-          sres = sreq.getResponse();
-          
-          sreq.setCoyoteRequest(req);
-          sres.setCoyoteResponse(res);
-          
-          req.setNote(CoyoteServer.ADAPTER_REQ_NOTE, sreq);
-          res.setNote(CoyoteServer.ADAPTER_RES_NOTE, sres);
-          
-          sres.setConnector();
-          
-        }
-        
-        lite.service(sreq, sres);
-        
-        if (res.getNote(CoyoteServer.COMET_RES_NOTE) == null) {
-          if (!sres.isCommitted()) {
-              res.sendHeaders();
-          }
-          sres.getOutputBuffer().flush();
-          res.finish();
-
-          sreq.recycle();
-          sres.recycle();
-        }
-    }
-    
-    // ---- Coyote ---
-    
-    @Override
-    public boolean event(Request req, Response res, SocketStatus status)
-        throws Exception {
-      return false;
-    }
-
-
-    public void setTomcatLite(TomcatLite lite) {
-        this.lite = lite;
-    }
-
-
-    @Override
-    public void setObjectManager(ObjectManager objectManager) {
-        getConnectors();
-        coyote.setObjectManager(objectManager);
-    }
-
-
-    
-}
diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/CoyoteServer.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/CoyoteServer.java
deleted file mode 100644 (file)
index 17c1e62..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-/*  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;
-
-import org.apache.coyote.Adapter;
-import org.apache.coyote.ProtocolHandler;
-import org.apache.coyote.http11.Http11NioProtocol;
-import org.apache.tomcat.integration.ObjectManager;
-
-
-/** 
- * Simple example of embeding coyote servlet.
- * 
- */
-public class CoyoteServer  {
-  protected int port = 8800;
-  protected boolean daemon = false;
-
-  /**
-   * Note indicating the response is COMET. 
-   */
-  public static final int COMET_RES_NOTE = 2;
-  public static final int COMET_REQ_NOTE = 2;
-  
-  public static final int ADAPTER_RES_NOTE = 1;    
-  public static final int ADAPTER_REQ_NOTE = 1;    
-  
-  protected ProtocolHandler proto;
-
-  protected Adapter adapter = new MapperAdapter();
-  protected int maxThreads = 20;
-  boolean started = false;
-  boolean async = false; // use old nio connector
-  
-  protected ObjectManager om;
-  
-  public CoyoteServer() {  
-  }
-  
-  public void setObjectManager(ObjectManager om) {
-      this.om = om;
-  }
-  
-  /** 
-   * Add an adapter. If more than the 'default' adapter is
-   * added, a MapperAdapter will be inserted.
-   * 
-   * @param path Use "/" for the default.
-   * @param adapter
-   */
-  public void addAdapter(String path, Adapter added) {
-      if ("/".equals(path)) {
-          ((MapperAdapter) adapter).setDefaultAdapter(added);        
-      } else {
-          ((MapperAdapter) adapter).getMapper().addWrapper(path, added);
-      }
-  }
-  
-  /**
-   */
-  public void run() {
-      try {
-          init();
-          start();
-      } catch(IOException ex) {
-          ex.printStackTrace();
-      }
-  }
-
-  public void setDaemon(boolean b) {
-    daemon = b;
-  }
-  
-  public void init() {
-    //JdkLoggerConfig.loadCustom();
-    om.bind("CoyoteServer:" + "CoyoteServer-" + port, 
-            this);
-    om.bind("CoyoteAdapter", adapter);
-  }
-
-  protected void initAdapters() {
-      if (proto == null) {
-          addProtocolHandler(port, daemon);
-      }
-    // adapter = ...
-    // Adapter secondaryadapter = ...
-    //registry.registerComponent(secondaryadapter, ":name=adapter", null);
-  }
-
-  public void stop() throws Exception {
-    if (!started) {
-      return;
-    }
-    proto.destroy();
-    started = false;
-  }
-  
-  /**
-   *  Simple CLI support - arg is a path:className pair.
-   */
-  public void setAdapter(String arg)  {
-    String[] pathClass = arg.split(":", 2);
-    try {
-      Class c = Class.forName(pathClass[1]);
-      Adapter a = (Adapter) c.newInstance();
-      addAdapter(pathClass[0],a);
-    } catch (Throwable e) {
-      e.printStackTrace();
-    }
-  }
-  
-  public void setPort(int port) {
-    if (proto != null) {
-        proto.setAttribute("port", Integer.toString(port));
-    }
-    this.port = port;
-  }
-  
-  public void setConnector(ProtocolHandler h) {
-      this.proto = h;
-      h.setAttribute("port", Integer.toString(port));
-
-      om.bind("ProtocolHandler:" + "ep-" + port, proto);
-  }
-  
-  public void addProtocolHandler(int port, boolean daemon) {
-      Http11NioProtocol proto = new Http11NioProtocol();
-      proto.setCompression("on");
-      proto.setCompressionMinSize(32);
-      proto.setPort(port);
-      proto.getEndpoint().setDaemon(daemon);
-      CoyoteServer server = this;
-      server.setConnector(proto);
-      server.setPort(port);
-      server.setDaemon(daemon);
-  }
-  
-  public void addProtocolHandler(ProtocolHandler proto, 
-                                 int port, boolean daemon) {
-      CoyoteServer server = this;
-      server.setConnector(proto);
-      server.setPort(port);
-      server.setDaemon(daemon);
-  }
-  
-
-  
-  public void start() throws IOException {
-    try {
-      if (started) {
-        return;
-      }
-      initAdapters();
-
-      // not required - should run fine without a connector.
-      if (proto != null) {
-          proto.setAdapter(adapter);
-      
-          proto.init();
-          proto.start();
-      }
-      
-      started = true;
-    } catch (Throwable e) {
-      e.printStackTrace();
-      throw new RuntimeException(e);
-    }
-  }
-  
-  public boolean getStarted() {
-    return started;
-  } 
-}
\ No newline at end of file
diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/CoyoteUtils.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/CoyoteUtils.java
deleted file mode 100644 (file)
index e97a450..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- */
-package org.apache.tomcat.lite.coyote;
-
-import java.io.IOException;
-
-import org.apache.coyote.Request;
-import org.apache.tomcat.util.buf.ByteChunk;
-import org.apache.tomcat.util.buf.MessageBytes;
-import org.apache.tomcat.util.http.MimeHeaders;
-import org.apache.tomcat.util.http.mapper.MappingData;
-
-public class CoyoteUtils {
-    static ByteChunk space = new ByteChunk(1);
-    static ByteChunk col = new ByteChunk(1);
-    static ByteChunk crlf = new ByteChunk(2);
-    static {
-        try {
-            space.append(' ');
-            col.append(':');
-            crlf.append('\r');
-            crlf.append('\n');
-        } catch (IOException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-    }
-
-    public static String getContextPath(Request request) {
-        MappingData md = MapperAdapter.getMappingData(request);
-        String ctxPath = (md.contextPath.isNull()) ? "/" : 
-            md.contextPath.toString();
-        return ctxPath;
-    }
-
-    public static String getPathInfo(Request request) {
-        MappingData md = MapperAdapter.getMappingData(request);
-        String ctxPath = (md.pathInfo.isNull()) ? "/" : 
-            md.pathInfo.toString();
-        return ctxPath;
-    }
-    public static String getServletPath(Request request) {
-        MappingData md = MapperAdapter.getMappingData(request);
-        String ctxPath = (md.wrapperPath.isNull()) ? "/" : 
-            md.wrapperPath.toString();
-        return ctxPath;
-    }
-    
-    // TODO: collate all notes in a signle file
-    static int READER_NOTE = 5;
-    
-    public static MessageReader getReader(Request req) {
-        MessageReader r = (MessageReader) req.getNote(READER_NOTE);
-        if (r == null) {
-            r = new MessageReader();
-            r.setRequest(req);
-            req.setNote(READER_NOTE, r);
-        }
-        return r;
-    }
-    
-    /** 
-     * Convert the request to bytes, ready to send.
-     */
-    public static void serializeRequest(Request req, 
-                                        ByteChunk reqBuf) throws IOException {
-        req.method().toBytes();
-        if (!req.unparsedURI().isNull()) {
-            req.unparsedURI().toBytes();
-        }
-        req.protocol().toBytes();
-
-        reqBuf.append(req.method().getByteChunk());
-        reqBuf.append(space);
-        if (req.unparsedURI().isNull()) {
-            req.requestURI().toBytes();
-
-            reqBuf.append(req.requestURI().getByteChunk());      
-        } else {
-            reqBuf.append(req.unparsedURI().getByteChunk());
-        }
-        reqBuf.append(space);
-        reqBuf.append(req.protocol().getByteChunk());
-        reqBuf.append(crlf);
-        // Headers
-        MimeHeaders mimeHeaders = req.getMimeHeaders();
-        boolean hasHost = false;
-        for (int i = 0; i < mimeHeaders.size(); i++) {
-            MessageBytes name = mimeHeaders.getName(i);
-            name.toBytes();
-            reqBuf.append(name.getByteChunk());
-            if (name.equalsIgnoreCase("host")) {
-                hasHost = true;
-            }
-            reqBuf.append(col);
-            mimeHeaders.getValue(i).toBytes();
-            reqBuf.append(mimeHeaders.getValue(i).getByteChunk());
-            reqBuf.append(crlf);
-        }
-        if (!hasHost) {
-            reqBuf.append("Host: localhost\r\n".getBytes(), 0, 17);
-        }
-        reqBuf.append(crlf);
-    }
-
-    
-}
diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/MapperAdapter.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/MapperAdapter.java
deleted file mode 100644 (file)
index 78ad37f..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*  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;
-import java.util.logging.Logger;
-
-import org.apache.coyote.Adapter;
-import org.apache.coyote.Request;
-import org.apache.coyote.Response;
-import org.apache.tomcat.util.buf.UriNormalizer;
-import org.apache.tomcat.util.http.mapper.BaseMapper;
-import org.apache.tomcat.util.http.mapper.MappingData;
-import org.apache.tomcat.util.net.SocketStatus;
-
-/**
- * 
- */
-public class MapperAdapter implements Adapter {
-
-    private BaseMapper mapper=new BaseMapper();
-    
-    static Logger log = Logger.getLogger("Mapper");
-    static final int MAP_NOTE = 4;
-    
-    public MapperAdapter() {
-        mapper.setDefaultHostName("localhost");
-        mapper.setContext("", new String[] {"index.html"},
-            null);
-    }
-
-    public MapperAdapter(BaseMapper mapper2) {
-        mapper = mapper2;
-    }
-    
-    public static MappingData getMappingData(Request req) {
-        MappingData md = (MappingData) req.getNote(MAP_NOTE);
-        if (md == null) {
-            md = new MappingData();
-            req.setNote(MAP_NOTE, md);
-        }
-        return md;
-    }
-
-    /**
-     * Copy an array of bytes to a different position. Used during 
-     * normalization.
-     */
-    public static void copyBytes(byte[] b, int dest, int src, int len) {
-        for (int pos = 0; pos < len; pos++) {
-            b[pos + dest] = b[pos + src];
-        }
-    }
-
-    
-    public void service(Request req, final Response res)
-            throws Exception {
-        long t0 = System.currentTimeMillis();
-        try {
-          // compute decodedURI - not done by connector
-          UriNormalizer.decodeRequest(req.decodedURI(), req.requestURI(), req.getURLDecoder());
-          MappingData mapRes = getMappingData(req);
-          mapRes.recycle();
-          
-          mapper.map(req.requestURI(), mapRes);
-
-          Adapter h=(Adapter)mapRes.wrapper;
-
-          if (h != null) {
-              log.info(">>>>>>>> START: " + req.method() + " " + 
-                        req.decodedURI() + " " + 
-                        h.getClass().getSimpleName());
-              h.service( req, res );
-          } else {
-              res.setStatus(404);
-          }
-        } catch(IOException ex) {
-            throw ex;
-        } catch( Throwable t ) {
-            t.printStackTrace();
-        } finally {
-            long t1 = System.currentTimeMillis();
-            
-            log.info("<<<<<<<< DONE: " + req.method() + " " + 
-                    req.decodedURI() + " " + 
-                    res.getStatus() + " " + 
-                    (t1 - t0));
-            
-            // Final processing
-            // TODO: only if not commet, this doesn't work with the 
-            // other connectors since we don't have the info
-            // TODO: add this note in the nio/apr connectors
-            // TODO: play nice with TomcatLite, other adapters that flush/close
-            if (res.getNote(CoyoteServer.COMET_RES_NOTE) == null) {
-                MessageWriter mw = MessageWriter.getWriter(req, res, 0);
-                mw.flush();
-                mw.recycle();
-                MessageReader reader = CoyoteUtils.getReader(req);
-                reader.recycle();
-                res.finish();
-
-                req.recycle();
-                res.recycle();
-            }
-        }
-    }
-
-    public BaseMapper getMapper() {
-      return mapper;
-    }
-
-    public void setDefaultAdapter(Adapter adapter) {
-        mapper.addWrapper("/", adapter);
-    }
-    
-    public boolean event(Request req, Response res, boolean error) throws Exception {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-    public boolean event(Request req, Response res, SocketStatus status)
-        throws Exception {
-      return false;
-    }
-
-}
\ No newline at end of file
diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/MessageReader.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/MessageReader.java
deleted file mode 100644 (file)
index 5215e5d..0000000
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- * 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;
-import java.io.InputStream;
-import java.io.Reader;
-import java.util.HashMap;
-
-import org.apache.coyote.Request;
-import org.apache.tomcat.util.buf.B2CConverter;
-import org.apache.tomcat.util.buf.ByteChunk;
-import org.apache.tomcat.util.buf.CharChunk;
-
-/**
- * Refactored from catalina.connector.InputBuffer. Renamed to avoid conflict
- * with coyote class.
- * 
- * TODO: move to coyote package.
- */
-
-/**
- * The buffer used by Tomcat request. This is a derivative of the Tomcat 3.3
- * OutputBuffer, adapted to handle input instead of output. This allows 
- * complete recycling of the facade objects (the ServletInputStream and the
- * BufferedReader).
- *
- * @author Remy Maucherat
- */
-public class MessageReader extends Reader
-    implements ByteChunk.ByteInputChannel, CharChunk.CharInputChannel,
-               CharChunk.CharOutputChannel {
-
-
-    // -------------------------------------------------------------- Constants
-
-
-    public static final String DEFAULT_ENCODING = 
-        org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING;
-    public static final int DEFAULT_BUFFER_SIZE = 8*1024;
-
-    // The buffer can be used for byte[] and char[] reading
-    // ( this is needed to support ServletInputStream and BufferedReader )
-    public final int INITIAL_STATE = 0;
-    public final int CHAR_STATE = 1;
-    public final int BYTE_STATE = 2;
-
-
-    // ----------------------------------------------------- Instance Variables
-
-
-    /**
-     * The byte buffer. More data may be added to it while reading.
-     */
-    private ByteChunk bb;
-
-
-    /**
-     * The chunk buffer, will be filled in from the bb.
-     */
-    private CharChunk cb;
-
-
-    /**
-     * State of the output buffer.
-     */
-    private int state = 0;
-
-
-    /**
-     * Number of bytes read.
-     */
-    private int bytesRead = 0;
-
-
-    /**
-     * Number of chars read.
-     */
-    private int charsRead = 0;
-
-
-    /**
-     * Flag which indicates if the input buffer is closed.
-     */
-    private boolean closed = false;
-
-    /**
-     * Encoding to use.
-     */
-    private String enc;
-
-
-    /**
-     * Encoder is set.
-     */
-    private boolean gotEnc = false;
-
-
-    /**
-     * Cached encoders.
-     */
-    protected HashMap<String, B2CConverter> encoders = 
-      new HashMap<String, B2CConverter>();
-
-
-    /**
-     * Current byte to char converter.
-     */
-    protected B2CConverter conv;
-
-
-    /**
-     * Associated Coyote request.
-     */
-    private Request coyoteRequest;
-
-
-    /**
-     * Buffer position.
-     */
-    private int markPos = -1;
-
-
-    /**
-     * Buffer size.
-     */
-    private int size = -1;
-
-
-    // ----------------------------------------------------------- Constructors
-
-
-    /**
-     * Default constructor. Allocate the buffer with the default buffer size.
-     */
-    public MessageReader() {
-        this(DEFAULT_BUFFER_SIZE);
-    }
-
-
-    /**
-     * Alternate constructor which allows specifying the initial buffer size.
-     * 
-     * @param size Buffer size to use
-     */
-    public MessageReader(int size) {
-        this.size = size;
-        bb = new ByteChunk(size);
-        bb.setLimit(size);
-        bb.setByteInputChannel(this);
-        cb = new CharChunk(size);
-        cb.setLimit(size);
-        cb.setOptimizedWrite(false);
-        cb.setCharInputChannel(this);
-        cb.setCharOutputChannel(this);
-    }
-
-
-    // ------------------------------------------------------------- Properties
-
-
-    /**
-     * Associated Coyote request.
-     * 
-     * @param coyoteRequest Associated Coyote request
-     */
-    public void setRequest(Request coyoteRequest) {
-       this.coyoteRequest = coyoteRequest;
-    }
-
-
-    /**
-     * Get associated Coyote request.
-     * 
-     * @return the associated Coyote request
-     */
-    public Request getRequest() {
-        return this.coyoteRequest;
-    }
-
-
-    // --------------------------------------------------------- Public Methods
-
-
-    /**
-     * Recycle the output buffer.
-     */
-    public void recycle() {
-        
-        state = INITIAL_STATE;
-        bytesRead = 0;
-        charsRead = 0;
-        
-        // If usage of mark made the buffer too big, reallocate it
-        if (cb.getChars().length > size) {
-            cb = new CharChunk(size);
-            cb.setLimit(size);
-            cb.setCharInputChannel(this);
-            cb.setCharOutputChannel(this);
-        } else {
-            cb.recycle();
-        }
-        markPos = -1;
-        bb.recycle(); 
-        closed = false;
-        
-        if (conv != null) {
-            conv.recycle();
-        }
-        
-        gotEnc = false;
-        enc = null;
-        
-    }
-
-
-    /**
-     * Close the input buffer.
-     * 
-     * @throws IOException An underlying IOException occurred
-     */
-    public void close()
-        throws IOException {
-        closed = true;
-    }
-
-
-    public int available()
-        throws IOException {
-        if (state == BYTE_STATE) {
-            return bb.getLength();
-        } else if (state == CHAR_STATE) {
-            return cb.getLength();
-        } else {
-            return 0;
-        }
-    }
-
-
-    // ------------------------------------------------- Bytes Handling Methods
-
-
-    /** 
-     * Reads new bytes in the byte chunk.
-     * 
-     * @param cbuf Byte buffer to be written to the response
-     * @param off Offset
-     * @param len Length
-     * 
-     * @throws IOException An underlying IOException occurred
-     */
-    public int realReadBytes(byte cbuf[], int off, int len)
-       throws IOException {
-
-        if (closed)
-            return -1;
-        if (coyoteRequest == null)
-            return -1;
-
-        state = BYTE_STATE;
-
-        int result = coyoteRequest.doRead(bb);
-
-        return result;
-
-    }
-
-
-    public int readByte()
-        throws IOException {
-        return bb.substract();
-    }
-
-
-    public int read(byte[] b, int off, int len)
-        throws IOException {
-        return bb.substract(b, off, len);
-    }
-
-
-    // ------------------------------------------------- Chars Handling Methods
-
-
-    /**
-     * Since the converter will use append, it is possible to get chars to
-     * be removed from the buffer for "writing". Since the chars have already
-     * been read before, they are ignored. If a mark was set, then the
-     * mark is lost.
-     */
-    public void realWriteChars(char c[], int off, int len) 
-        throws IOException {
-        markPos = -1;
-    }
-
-
-    public void setEncoding(String s) {
-        enc = s;
-    }
-
-    /** 
-     * Called when a read(char[]) operation is lacking data. It will read
-     * bytes.
-     */
-    public int realReadChars(char cbuf[], int off, int len)
-        throws IOException {
-
-        if (!gotEnc)
-            setConverter();
-
-        if (bb.getLength() <= 0) {
-            int nRead = realReadBytes(bb.getBytes(), 0, bb.getBytes().length);
-            if (nRead < 0) {
-                return -1;
-            }
-        }
-
-        if (markPos == -1) {
-            cb.setOffset(0);
-            cb.setEnd(0);
-        }
-
-        conv.convert(bb, cb, -1);
-        bb.setOffset(bb.getEnd());
-        state = CHAR_STATE;
-
-        return cb.getLength();
-
-    }
-
-
-    public int read()
-        throws IOException {
-        return cb.substract();
-    }
-
-
-    public int read(char[] cbuf)
-        throws IOException {
-        return read(cbuf, 0, cbuf.length);
-    }
-
-
-    public int read(char[] cbuf, int off, int len)
-        throws IOException {
-        return cb.substract(cbuf, off, len);
-    }
-
-
-    public long skip(long n)
-        throws IOException {
-
-        if (n < 0) {
-            throw new IllegalArgumentException();
-        }
-
-        long nRead = 0;
-        while (nRead < n) {
-            if (cb.getLength() >= n) {
-                cb.setOffset(cb.getStart() + (int) n);
-                nRead = n;
-            } else {
-                nRead += cb.getLength();
-                cb.setOffset(cb.getEnd());
-                int toRead = 0;
-                if (cb.getChars().length < (n - nRead)) {
-                    toRead = cb.getChars().length;
-                } else {
-                    toRead = (int) (n - nRead);
-                }
-                int nb = realReadChars(cb.getChars(), 0, toRead);
-                if (nb < 0)
-                    break;
-            }
-        }
-
-        return nRead;
-
-    }
-
-
-    public boolean ready()
-        throws IOException {
-        return (cb.getLength() > 0);
-    }
-
-
-    public boolean markSupported() {
-        return true;
-    }
-
-
-    public void mark(int readAheadLimit)
-        throws IOException {
-        if (cb.getLength() <= 0) {
-            cb.setOffset(0);
-            cb.setEnd(0);
-        } else {
-            if ((cb.getBuffer().length > (2 * size)) 
-                && (cb.getLength()) < (cb.getStart())) {
-                System.arraycopy(cb.getBuffer(), cb.getStart(), 
-                                 cb.getBuffer(), 0, cb.getLength());
-                cb.setEnd(cb.getLength());
-                cb.setOffset(0);
-            }
-        }
-        int offset = readAheadLimit;
-        if (offset < size) {
-            offset = size;
-        }
-        cb.setLimit(cb.getStart() + offset);
-        markPos = cb.getStart();
-    }
-
-
-    public void reset()
-        throws IOException {
-        if (state == CHAR_STATE) {
-            if (markPos < 0) {
-                cb.recycle();
-                markPos = -1;
-                throw new IOException();
-            } else {
-                cb.setOffset(markPos);
-            }
-        } else {
-            bb.recycle();
-        }
-    }
-
-
-    protected void setConverter()
-        throws IOException {
-        if (coyoteRequest != null)
-            enc = coyoteRequest.getCharacterEncoding();
-
-        gotEnc = true;
-        if (enc == null)
-            enc = DEFAULT_ENCODING;
-        conv = (B2CConverter) encoders.get(enc);
-        if (conv == null) {
-          conv = new B2CConverter(enc);
-          encoders.put(enc, conv);
-        }
-    }
-    
-    public class MRInputStream extends InputStream {
-        public long skip(long n)
-                throws IOException {
-            return MessageReader.this.skip(n);
-        }
-
-        public void mark(int readAheadLimit)
-        {
-            try {
-                MessageReader.this.mark(readAheadLimit);
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-        }
-
-
-        public void reset()
-        throws IOException {
-            MessageReader.this.reset();
-        }
-
-
-
-        public int read()
-        throws IOException {    
-            return MessageReader.this.readByte();
-        }
-
-        public int available() throws IOException {
-            return MessageReader.this.available();
-        }
-
-        public int read(final byte[] b) throws IOException {
-            return MessageReader.this.read(b, 0, b.length);
-        }
-
-
-        public int read(final byte[] b, final int off, final int len)
-        throws IOException {
-
-            return MessageReader.this.read(b, off, len);
-        }
-
-
-        /** 
-         * Close the stream
-         * Since we re-cycle, we can't allow the call to super.close()
-         * which would permantely disable us.
-         */
-        public void close() throws IOException {
-            MessageReader.this.close();
-        }
-    }
-    
-    MRInputStream is = new MRInputStream();
-    
-    public InputStream asInputStream() {
-        return is;
-    }
-}
diff --git a/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/MessageWriter.java b/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/MessageWriter.java
deleted file mode 100644 (file)
index f53e534..0000000
+++ /dev/null
@@ -1,694 +0,0 @@
-/*
- * 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;
-import java.io.Writer;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.HashMap;
-
-import org.apache.coyote.ActionCode;
-import org.apache.coyote.Request;
-import org.apache.coyote.Response;
-import org.apache.tomcat.util.buf.ByteChunk;
-import org.apache.tomcat.util.buf.C2BConverter;
-import org.apache.tomcat.util.buf.CharChunk;
-
-/*
- * Refactoring: original code in catalina.connector.
- * - renamed to OutputWriter to avoid confusion with coyote OutputBuffer
- * - 
- * TODO: move it to coyote, add Response.getWriter 
- * 
- */
-
-/**
- * The buffer used by Tomcat response. This is a derivative of the Tomcat 3.3
- * OutputBuffer, with the removal of some of the state handling (which in 
- * Coyote is mostly the Processor's responsability).
- *
- * @author Costin Manolache
- * @author Remy Maucherat
- */
-public class MessageWriter extends Writer
-    implements ByteChunk.ByteOutputChannel, CharChunk.CharOutputChannel {
-
-    // used in getWriter, until a method is added to res.
-    private static final int WRITER_NOTE = 3;
-
-    // -------------------------------------------------------------- Constants
-
-
-    public static final String DEFAULT_ENCODING = 
-        org.apache.coyote.Constants.DEFAULT_CHARACTER_ENCODING;
-    public static final int DEFAULT_BUFFER_SIZE = 8*1024;
-
-
-    // The buffer can be used for byte[] and char[] writing
-    // ( this is needed to support ServletOutputStream and for
-    // efficient implementations of templating systems )
-    public final int INITIAL_STATE = 0;
-    public final int CHAR_STATE = 1;
-    public final int BYTE_STATE = 2;
-
-
-    // ----------------------------------------------------- Instance Variables
-
-
-    /**
-     * The byte buffer.
-     */
-    private ByteChunk bb;
-
-
-    /**
-     * The chunk buffer.
-     */
-    private CharChunk cb;
-
-
-    /**
-     * State of the output buffer.
-     */
-    private int state = 0;
-
-
-    /**
-     * Number of bytes written.
-     */
-    private int bytesWritten = 0;
-
-
-    /**
-     * Number of chars written.
-     */
-    private int charsWritten = 0;
-
-
-    /**
-     * Flag which indicates if the output buffer is closed.
-     */
-    private boolean closed = false;
-
-
-    /**
-     * Do a flush on the next operation.
-     */
-    private boolean doFlush = false;
-
-
-    /**
-     * Byte chunk used to output bytes. This is just used to wrap the byte[]
-     * to match the coyote OutputBuffer interface
-     */
-    private ByteChunk outputChunk = new ByteChunk();
-
-
-    /**
-     * Encoding to use. 
-     * TODO: isn't it redundant ? enc, gotEnc, conv plus the enc in the bb
-     */
-    private String enc;
-
-
-    /**
-     * Encoder is set.
-     */
-    private boolean gotEnc = false;
-
-
-    /**
-     * List of encoders. The writer is reused - the encoder mapping 
-     * avoids creating expensive objects. In future it'll contain nio.Charsets
-     */
-    protected HashMap encoders = new HashMap();
-
-
-    /**
-     * Current char to byte converter. TODO: replace with Charset
-     */
-    protected C2BConverter conv;
-
-
-    /**
-     * Associated Coyote response.
-     */
-    private Response coyoteResponse;
-
-
-    /**
-     * Suspended flag. All output bytes will be swallowed if this is true.
-     */
-    private boolean suspended = false;
-
-
-    // ----------------------------------------------------------- Constructors
-
-
-    /**
-     * Default constructor. Allocate the buffer with the default buffer size.
-     */
-    public MessageWriter() {
-
-        this(DEFAULT_BUFFER_SIZE);
-
-    }
-
-
-    /**
-     * Alternate constructor which allows specifying the initial buffer size.
-     * 
-     * @param size Buffer size to use
-     */
-    public MessageWriter(int size) {
-
-        bb = new ByteChunk(size);
-        bb.setLimit(size);
-        bb.setByteOutputChannel(this);
-        cb = new CharChunk(size);
-        cb.setCharOutputChannel(this);
-        cb.setLimit(size);
-
-    }
-
-
-    // ------------------------------------------------------------- Properties
-
-
-    /**
-     * Associated Coyote response.
-     * 
-     * @param coyoteResponse Associated Coyote response
-     */
-    public void setResponse(Response coyoteResponse) {
-       this.coyoteResponse = coyoteResponse;
-    }
-
-
-    /**
-     * Get associated Coyote response.
-     * 
-     * @return the associated Coyote response
-     */
-    public Response getResponse() {
-        return this.coyoteResponse;
-    }
-
-
-    /**
-     * Is the response output suspended ?
-     * 
-     * @return suspended flag value
-     */
-    public boolean isSuspended() {
-        return this.suspended;
-    }
-
-
-    /**
-     * Set the suspended flag.
-     * 
-     * @param suspended New suspended flag value
-     */
-    public void setSuspended(boolean suspended) {
-        this.suspended = suspended;
-    }
-
-
-    // --------------------------------------------------------- Public Methods
-
-
-    /**
-     * Recycle the output buffer.
-     */
-    public void recycle() {
-        
-        state = INITIAL_STATE;
-        bytesWritten = 0;
-        charsWritten = 0;
-        
-        cb.recycle();
-        bb.recycle(); 
-        closed = false;
-        suspended = false;
-        
-        if (conv!= null) {
-            conv.recycle();
-        }
-        
-        gotEnc = false;
-        enc = null;
-        
-    }
-
-
-    /**
-     * Close the output buffer. This tries to calculate the response size if 
-     * the response has not been committed yet.
-     * 
-     * @throws IOException An underlying IOException occurred
-     */
-    public void close()
-        throws IOException {
-
-        if (closed)
-            return;
-        if (suspended)
-            return;
-
-        if ((!coyoteResponse.isCommitted()) 
-            && (coyoteResponse.getContentLengthLong() == -1)) {
-            // Flushing the char buffer
-            if (state == CHAR_STATE) {
-                cb.flushBuffer();
-                state = BYTE_STATE;
-            }
-            // If this didn't cause a commit of the response, the final content
-            // length can be calculated
-            if (!coyoteResponse.isCommitted()) {
-                coyoteResponse.setContentLength(bb.getLength());
-            }
-        }
-
-        doFlush(false);
-        closed = true;
-
-        coyoteResponse.finish();
-
-    }
-
-
-    /**
-     * Flush bytes or chars contained in the buffer.
-     * 
-     * @throws IOException An underlying IOException occurred
-     */
-    public void flush()
-        throws IOException {
-        doFlush(true);
-    }
-
-
-    /**
-     * Flush bytes or chars contained in the buffer.
-     * 
-     * @throws IOException An underlying IOException occurred
-     */
-    protected void doFlush(boolean realFlush)
-        throws IOException {
-
-        if (suspended)
-            return;
-
-        doFlush = true;
-        if (state == CHAR_STATE) {
-            cb.flushBuffer();
-            bb.flushBuffer();
-            state = BYTE_STATE;
-        } else if (state == BYTE_STATE) {
-            bb.flushBuffer();
-        } else if (state == INITIAL_STATE) {
-            // If the buffers are empty, commit the response header
-            coyoteResponse.sendHeaders();
-        }
-        doFlush = false;
-
-        if (realFlush) {
-            coyoteResponse.action(ActionCode.ACTION_CLIENT_FLUSH, 
-                                  coyoteResponse);
-            // If some exception occurred earlier, or if some IOE occurred
-            // here, notify the servlet with an IOE
-            if (coyoteResponse.isExceptionPresent()) {
-                throw new ClientAbortException
-                    (coyoteResponse.getErrorException());
-            }
-        }
-
-    }
-
-
-    // ------------------------------------------------- Bytes Handling Methods
-
-
-    /** 
-     * Sends the buffer data to the client output, checking the
-     * state of Response and calling the right interceptors.
-     * 
-     * @param buf Byte buffer to be written to the response
-     * @param off Offset
-     * @param cnt Length
-     * 
-     * @throws IOException An underlying IOException occurred
-     */
-    public void realWriteBytes(byte buf[], int off, int cnt)
-       throws IOException {
-
-        if (closed)
-            return;
-        if (coyoteResponse == null)
-            return;
-
-        // If we really have something to write
-        if (cnt > 0) {
-            // real write to the adapter
-            outputChunk.setBytes(buf, off, cnt);
-            try {
-                coyoteResponse.doWrite(outputChunk);
-            } catch (IOException e) {
-                // An IOException on a write is almost always due to
-                // the remote client aborting the request.  Wrap this
-                // so that it can be handled better by the error dispatcher.
-                throw new ClientAbortException(e);
-            }
-        }
-
-    }
-
-
-    public void write(byte b[], int off, int len) throws IOException {
-
-        if (suspended)
-            return;
-
-        if (state == CHAR_STATE)
-            cb.flushBuffer();
-        state = BYTE_STATE;
-        writeBytes(b, off, len);
-
-    }
-
-
-    private void writeBytes(byte b[], int off, int len) 
-        throws IOException {
-
-        if (closed)
-            return;
-
-        bb.append(b, off, len);
-        bytesWritten += len;
-
-        // if called from within flush(), then immediately flush
-        // remaining bytes
-        if (doFlush) {
-            bb.flushBuffer();
-        }
-
-    }
-
-
-    public void writeByte(int b)
-        throws IOException {
-
-        if (suspended)
-            return;
-
-        if (state == CHAR_STATE)
-            cb.flushBuffer();
-        state = BYTE_STATE;
-
-        bb.append( (byte)b );
-        bytesWritten++;
-
-    }
-
-
-    // ------------------------------------------------- Chars Handling Methods
-
-
-    public void write(int c)
-        throws IOException {
-
-        if (suspended)
-            return;
-
-        state = CHAR_STATE;
-
-        cb.append((char) c);
-        charsWritten++;
-
-    }
-
-
-    public void write(char c[])
-        throws IOException {
-
-        if (suspended)
-            return;
-
-        write(c, 0, c.length);
-
-    }
-
-
-    public void write(char c[], int off, int len)
-        throws IOException {
-
-        if (suspended)
-            return;
-
-        state = CHAR_STATE;
-
-        cb.append(c, off, len);
-        charsWritten += len;
-
-    }
-
-
-    public void write(StringBuffer sb)
-        throws IOException {
-
-        if (suspended)
-            return;
-
-        state = CHAR_STATE;
-
-        int len = sb.length();
-        charsWritten += len;
-        cb.append(sb);
-
-    }
-
-
-    /**
-     * Append a string to the buffer
-     */
-    public void write(String s, int off, int len)
-        throws IOException {
-
-        if (suspended)
-            return;
-
-        state=CHAR_STATE;
-
-        charsWritten += len;
-        if (s==null)
-            s="null";
-        cb.append( s, off, len );
-
-    }
-
-
-    public void write(String s)
-        throws IOException {
-
-        if (suspended)
-            return;
-
-        state = CHAR_STATE;
-        if (s==null)
-            s="null";
-        write(s, 0, s.length());
-
-    } 
-
-    public void println() throws IOException {
-        write("\n");
-    }
-
-    public void println(String s) throws IOException {
-        write(s);
-        write("\n");
-    }
-
-    public void print(String s) throws IOException {
-        write(s);
-    }
-
-    public void flushChars()
-        throws IOException {
-
-        cb.flushBuffer();
-        state = BYTE_STATE;
-
-    }
-
-
-    public boolean flushCharsNeeded() {
-        return state == CHAR_STATE;
-    }
-
-
-    public void setEncoding(String s) {
-        enc = s;
-    }
-
-
-    public void realWriteChars(char c[], int off, int len) 
-        throws IOException {
-
-        if (!gotEnc)
-            setConverter();
-
-        conv.convert(c, off, len);
-        conv.flushBuffer();    // ???
-
-    }
-
-
-    public void checkConverter() 
-        throws IOException {
-
-        if (!gotEnc)
-            setConverter();
-
-    }
-
-
-    protected void setConverter() 
-        throws IOException {
-
-        if (coyoteResponse != null)
-            enc = coyoteResponse.getCharacterEncoding();
-
-        gotEnc = true;
-        if (enc == null)
-            enc = DEFAULT_ENCODING;
-        conv = (C2BConverter) encoders.get(enc);
-        if (conv == null) {
-            
-            if (System.getSecurityManager() != null){
-                try{
-                    conv = (C2BConverter)AccessController.doPrivileged(
-                            new PrivilegedExceptionAction(){
-
-                                public Object run() throws IOException{
-                                    return new C2BConverter(bb, enc);
-                                }
-
-                            }
-                    );              
-                }catch(PrivilegedActionException ex){
-                    Exception e = ex.getException();
-                    if (e instanceof IOException)
-                        throw (IOException)e; 
-                }
-            } else {
-                conv = new C2BConverter(bb, enc);
-            }
-            
-            encoders.put(enc, conv);
-
-        }
-    }
-
-    
-    // --------------------  BufferedOutputStream compatibility
-
-
-    /**
-     * Real write - this buffer will be sent to the client
-     */
-    public void flushBytes()
-        throws IOException {
-
-        bb.flushBuffer();
-
-    }
-
-
-    public int getBytesWritten() {
-        return bytesWritten;
-    }
-
-
-    public int getCharsWritten() {
-        return charsWritten;
-    }
-
-
-    public int getContentWritten() {
-        return bytesWritten + charsWritten;
-    }
-
-
-    /** 
-     * True if this buffer hasn't been used ( since recycle() ) -
-     * i.e. no chars or bytes have been added to the buffer.  
-     */
-    public boolean isNew() {
-        return (bytesWritten == 0) && (charsWritten == 0);
-    }
-
-
-    public void setBufferSize(int size) {
-        if (size > bb.getLimit()) {// ??????
-           bb.setLimit(size);
-       }
-    }
-
-
-    public void reset() {
-
-        //count=0;
-        bb.recycle();
-        bytesWritten = 0;
-        cb.recycle();
-        charsWritten = 0;
-        gotEnc = false;
-        enc = null;
-        state = INITIAL_STATE;
-    }
-
-
-    public int getBufferSize() {
-       return bb.getLimit();
-    }
-
-
-    public static MessageWriter getWriter(Request req, Response res, int size) 
-    {        
-        MessageWriter out=(MessageWriter)req.getNote(MessageWriter.WRITER_NOTE);
-        if( out == null ) {
-            if( size<=0 ) {
-                out=new MessageWriter();
-            } else {
-                out=new MessageWriter(size);
-            }
-            out.setResponse(res);
-            req.setNote(MessageWriter.WRITER_NOTE, out );
-        }
-        return out;
-    }
-
-    public ByteChunk getByteBuffer() {
-      return outputChunk;
-    }
-
-}
index dff9e34..fe2673e 100644 (file)
@@ -5,8 +5,8 @@ package org.apache.tomcat.lite.webxml;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 
-import org.apache.tomcat.lite.ServletContextImpl;
 import org.apache.tomcat.lite.ContextPreinitListener;
+import org.apache.tomcat.lite.ServletContextImpl;
 
 /**
  * Default configurator - parse web.xml, init the context.
index 65a3fc1..2611050 100644 (file)
@@ -4,10 +4,7 @@ package org.apache.tomcat.lite.webxml;
 
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
 import java.io.InputStream;
-import java.io.ObjectOutputStream;
 import java.util.ArrayList;
 import java.util.HashMap;
 
@@ -39,16 +36,6 @@ public class WebXml {
         d = cfg;
     }
 
-    /**
-     * Serialize the data, for caching. 
-     */
-    public void saveWebAppData(String fileName) throws IOException {
-        ObjectOutputStream oos = 
-            new ObjectOutputStream(new FileOutputStream(fileName));
-        oos.writeObject(d);
-        oos.close();
-    }
-    
     public ServletContextConfig getWebAppData() {
         return d;
     }
index d9986b9..2200694 100644 (file)
@@ -33,7 +33,6 @@ import java.util.Date;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.Locale;
-import java.util.Map;
 import java.util.StringTokenizer;
 
 import javax.servlet.ServletException;
@@ -42,6 +41,9 @@ import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.tomcat.addons.Filesystem;
+import org.apache.tomcat.integration.ObjectManager;
+import org.apache.tomcat.integration.simple.ServletHelper;
 import org.apache.tomcat.servlets.util.Range;
 
 /**
@@ -56,7 +58,6 @@ public class DefaultServlet  extends HttpServlet {
 
 
     // ----------------------------------------------------- Instance Variables
-    
 
     /**
      * Should we generate directory listings?
@@ -126,6 +127,8 @@ public class DefaultServlet  extends HttpServlet {
 
     // --------------------------------------------------------- Public Methods
 
+    protected ObjectManager om;
+    protected Filesystem fs;
 
     /**
      * Finalize this servlet.
@@ -138,6 +141,9 @@ public class DefaultServlet  extends HttpServlet {
      * Initialize this servlet.
      */
     public void init() throws ServletException {
+        om = ServletHelper.getObjectManager(getServletContext());
+        fs = (Filesystem) om.get(Filesystem.class.getName());
+
         String realPath = getServletContext().getRealPath("/");
         basePath = new File(realPath);
         try {
@@ -145,6 +151,7 @@ public class DefaultServlet  extends HttpServlet {
         } catch (IOException e) {
             basePathName = basePath.getAbsolutePath();
         }
+        log("Init fs " + fs + " base: " + basePathName);
         
         // Set our properties from the initialization parameters
         String value = null;
@@ -177,9 +184,42 @@ public class DefaultServlet  extends HttpServlet {
             input = 256;
         if (output < 256)
             output = 256;
+    }
 
+    public void setFilesystem(Filesystem fs) {
+        this.fs = fs;
+    }
+    
+    public Filesystem getFilesystem() {
+        return fs;
+    }
+    
+    public void setBasePath(String s) {
+        this.basePathName = s;
+        this.basePath = new File(s);
+    }
+    
+    public String getBasePath() {
+        return basePathName;
+    }
+    
+    public void setInput(int i) {
+        this.input = i;
+    }
+    
+    public void setListings(boolean b) {
+        this.listings = b;
+    }
+
+    public void setReadme(String s) {
+        readmeFile = s;
     }
 
+    public void setFileEncoding(String s) {
+        fileEncoding = s;
+    }
+    
+    
     public void loadDefaultMime() throws IOException {
         File mimeF = new File("/etc/mime.types");
         boolean loaded =false;
@@ -349,9 +389,9 @@ public class DefaultServlet  extends HttpServlet {
         int cacheSize;
         public LRUFileCache() {
         }
-        protected boolean removeEldestEntity(Map.Entry eldest) {
-            return size() > cacheSize;
-        }
+//        protected boolean removeEldestEntity(Map.Entry eldest) {
+//            return size() > cacheSize;
+//        }
     }
     
 
index 93563e6..68fe811 100644 (file)
@@ -18,10 +18,9 @@ package org.apache.tomcat.servlets.file;
 
 
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.io.Writer;
 import java.text.SimpleDateFormat;
 import java.util.Date;
@@ -121,7 +120,7 @@ public class WebdavServlet extends DefaultServlet {
     }
 
     // TODO: replace it with writeRole - who is enabled to write
-    protected boolean readOnly = false;
+    protected boolean readOnly = true;
 
     /**
      * Repository of the lock-null resources.
@@ -152,9 +151,16 @@ public class WebdavServlet extends DefaultServlet {
         } catch (Throwable t) {
             ;
         }
+        log("Starting webdav");
     }
 
-
+    public void setReadonly(boolean ro) {
+        readOnly = ro;
+    }
+    
+    public boolean getReadonly() {
+        return readOnly;
+    }
     // ------------------------------------------------------ Protected Methods
 
     /**
@@ -834,7 +840,7 @@ public class WebdavServlet extends DefaultServlet {
 
         try {
             // will override 
-            FileOutputStream fos = new FileOutputStream(resFile);
+            OutputStream fos = getFilesystem().getOutputStream(resFile.getPath());
             CopyUtils.copy(resourceInputStream, fos);
         } catch(IOException e) {
             result = false;
@@ -1215,8 +1221,8 @@ public class WebdavServlet extends DefaultServlet {
         } else {
 
             try {
-                CopyUtils.copy( new FileInputStream(object), 
-                    new FileOutputStream(dest));
+                CopyUtils.copy(getFilesystem().getInputStream(object.getPath()), 
+                    getFilesystem().getOutputStream(dest));
             } catch(IOException ex ) {
                 errorList.put
                 (source,
index 278bfbc..4c74405 100644 (file)
@@ -26,13 +26,13 @@ import javax.servlet.ServletConfig;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
 
-import org.apache.tomcat.InstanceManager;
 import org.apache.jasper.EmbeddedServletOptions;
 import org.apache.jasper.JasperException;
 import org.apache.jasper.JspC;
 import org.apache.jasper.Options;
 import org.apache.jasper.compiler.JspRuntimeContext;
 import org.apache.jasper.servlet.JspServletWrapper;
+import org.apache.tomcat.InstanceManager;
 
 /** 
  * The actual compiler. Maps and compile a jsp-file to a class.
index fa98e5a..c17c829 100644 (file)
@@ -23,8 +23,6 @@ import java.security.Principal;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.addons.UserAuthentication;
 
 
@@ -33,7 +31,6 @@ import org.apache.tomcat.addons.UserAuthentication;
  */
 public class BasicAuthentication implements UserAuthentication {
 
-    private static Log log = LogFactory.getLog(BasicAuthentication.class);
     String realm;
     
     @Override
index d02908f..5535790 100644 (file)
@@ -23,8 +23,6 @@ import java.security.Principal;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.addons.UserAuthentication;
 
 
@@ -33,7 +31,6 @@ import org.apache.tomcat.addons.UserAuthentication;
  */
 public class FormAuthentication implements UserAuthentication {
 
-    private static Log log = LogFactory.getLog(FormAuthentication.class);
     String realm;
     String url;
     
index a216b82..0cc2152 100644 (file)
 package org.apache.tomcat.servlets.sec;
 
 
-import java.io.IOException;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Properties;
 
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
 
 /** 
  * Load user/passwords from a file.
index 4c73f52..3885ca1 100644 (file)
@@ -23,6 +23,7 @@ import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.logging.Level;
 
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpSession;
@@ -362,7 +363,7 @@ public class HttpSessionImpl  implements HttpSession, Serializable {
                 try {
                     ((HttpSessionBindingListener) value).valueBound(event);
                 } catch (Throwable t){
-                    manager.log.error("Listener valueBound() error", t); 
+                    manager.log.log(Level.SEVERE, "Listener valueBound() error", t); 
                 }
             }
         }
@@ -377,7 +378,7 @@ public class HttpSessionImpl  implements HttpSession, Serializable {
                 ((HttpSessionBindingListener) unbound).valueUnbound
                     (new HttpSessionBindingEvent(getSession(), name));
             } catch (Throwable t) {
-                manager.log.error("Listener valueUnbound()", t);
+                manager.log.log(Level.SEVERE, "Listener valueUnbound()", t);
             }
         }
 
@@ -406,7 +407,7 @@ public class HttpSessionImpl  implements HttpSession, Serializable {
                     listener.attributeAdded(event);
                 }
             } catch (Throwable t) {
-                manager.log.error("Listener attibuteAdded/Replaced()", t);
+                manager.log.log(Level.SEVERE, "Listener attibuteAdded/Replaced()", t);
             }
         }
 
@@ -462,7 +463,7 @@ public class HttpSessionImpl  implements HttpSession, Serializable {
                 try {
                     listener.sessionCreated(event);
                 } catch (Throwable t) {
-                    manager.log.error("listener.sessionCreated()", t);
+                    manager.log.log(Level.SEVERE, "listener.sessionCreated()", t);
                 }
             }
         }
@@ -592,7 +593,7 @@ public class HttpSessionImpl  implements HttpSession, Serializable {
                     try {
                         listener.sessionDestroyed(event);
                     } catch (Throwable t) {
-                        manager.log.error("listener.sessionDestroyed", t);
+                        manager.log.log(Level.SEVERE, "listener.sessionDestroyed", t);
                     }
                 }
             }
@@ -720,7 +721,7 @@ public class HttpSessionImpl  implements HttpSession, Serializable {
                 }
                 listener.attributeRemoved(event);
             } catch (Throwable t) {
-                manager.log.error("listener.attributeRemoved", t);
+                manager.log.log(Level.SEVERE, "listener.attributeRemoved", t);
             }
         }
 
index a4a6921..54c0063 100644 (file)
@@ -8,9 +8,8 @@ import java.lang.reflect.Method;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.Random;
-
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 /**
  *  Generates random IDs, useable as cookies.
@@ -24,7 +23,7 @@ public class RandomGenerator {
     protected DataInputStream randomIS=null;
     protected String devRandomSource="/dev/urandom";
 
-    protected static Log log = LogFactory.getLog(RandomGenerator.class);
+    protected static Logger log = Logger.getLogger(RandomGenerator.class.getName());
 
     /**
      * The message digest algorithm to be used when generating session
@@ -92,17 +91,17 @@ public class RandomGenerator {
             try {
                 this.digest = MessageDigest.getInstance(algorithm);
             } catch (NoSuchAlgorithmException e) {
-                log.error("Algorithm not found", e);
+                log.log(Level.SEVERE, "Algorithm not found", e);
                 try {
                     this.digest = MessageDigest.getInstance("MD5");
                 } catch (NoSuchAlgorithmException f) {
-                    log.error("No message digest available", f);
+                    log.log(Level.SEVERE, "No message digest available", f);
                     this.digest = null;
                 }
             }
             long t2=System.currentTimeMillis();
-            if( log.isDebugEnabled() )
-                log.debug("getDigest() " + (t2-t1));
+            if( log.isLoggable(Level.FINEST) )
+                log.finest("getDigest() " + (t2-t1));
         }
 
         return (this.digest);
@@ -159,8 +158,6 @@ public class RandomGenerator {
                 if (len == bytes.length) {
                     return;
                 }
-                if(log.isDebugEnabled())
-                    log.debug("Got " + len + " " + bytes.length );
             } catch (Exception ex) {
                 // Ignore
             }
@@ -169,7 +166,7 @@ public class RandomGenerator {
             try {
                 randomIS.close();
             } catch (Exception e) {
-                log.warn("Failed to close randomIS.");
+                log.warning("Failed to close randomIS.");
             }
             
             randomIS = null;
@@ -199,14 +196,14 @@ public class RandomGenerator {
                 this.random.setSeed(seed);
             } catch (Exception e) {
                 // Fall back to the simple case
-                log.error("Failed to create random " + randomClass, e);
+                log.log(Level.SEVERE, "Failed to create random " + randomClass, e);
                 this.random = new java.util.Random();
                 this.random.setSeed(seed);
             }
-            if(log.isDebugEnabled()) {
+            if(log.isLoggable(Level.FINEST)) {
                 long t2=System.currentTimeMillis();
                 if( (t2-t1) > 100 )
-                    log.debug("Init random: " + " " + (t2-t1));
+                    log.finest("Init random: " + " " + (t2-t1));
             }
         }
         
@@ -309,13 +306,13 @@ public class RandomGenerator {
             if( ! f.exists() ) return;
             randomIS= new DataInputStream( new FileInputStream(f));
             randomIS.readLong();
-            if( log.isDebugEnabled() )
-                log.debug( "Opening " + devRandomSource );
+//            if( log.isDebugEnabled() )
+//                log.debug( "Opening " + devRandomSource );
         } catch( IOException ex ) {
             try {
                 randomIS.close();
             } catch (Exception e) {
-                log.warn("Failed to close randomIS.");
+                log.warning("Failed to close randomIS.");
             }
             
             randomIS=null;
index 72400ea..2d30d95 100644 (file)
@@ -23,17 +23,16 @@ import java.util.ArrayList;
 import java.util.Date;
 import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Timer;
 import java.util.TimerTask;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import javax.servlet.ServletContext;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
 
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.addons.UserSessionManager;
 
 // TODO: move 'expiring objects' to a separate utility class
@@ -48,7 +47,7 @@ import org.apache.tomcat.addons.UserSessionManager;
  * @author Craig R. McClanahan
  */
 public class SimpleSessionManager implements UserSessionManager {
-    protected static Log log = LogFactory.getLog(SimpleSessionManager.class);
+    protected static Logger log = Logger.getLogger(SimpleSessionManager.class.getName());
 
     protected RandomGenerator randomG = new RandomGenerator();
     
@@ -89,17 +88,17 @@ public class SimpleSessionManager implements UserSessionManager {
     protected int expiredSessions = 0;
 
     static class SessionLRU extends LinkedHashMap {
-        protected boolean removeEldestEntry(Map.Entry eldest) {
-            HttpSessionImpl s = (HttpSessionImpl)eldest.getValue();
-            int size = this.size();
-            
-            // TODO: check if eldest is expired or if we're above the limit.
-            // if eldest is expired, turn a flag to check for more.
-            
-            // Note: this doesn't work well for sessions that set shorter
-            // expiry time, or longer expiry times. 
-            return false;
-        }
+//        protected boolean removeEldestEntry(Map.Entry eldest) {
+//            HttpSessionImpl s = (HttpSessionImpl)eldest.getValue();
+//            int size = this.size();
+//            
+//            // TODO: check if eldest is expired or if we're above the limit.
+//            // if eldest is expired, turn a flag to check for more.
+//            
+//            // Note: this doesn't work well for sessions that set shorter
+//            // expiry time, or longer expiry times. 
+//            return false;
+//        }
 
     }
     
@@ -314,8 +313,8 @@ public class SimpleSessionManager implements UserSessionManager {
         HttpSessionImpl sessions[] = findSessions();
         int expireHere = 0 ;
         
-        if(log.isDebugEnabled())
-            log.debug("Start expire sessions "  + " at " + timeNow + " sessioncount " + sessions.length);
+        if(log.isLoggable(Level.FINE))
+            log.fine("Start expire sessions "  + " at " + timeNow + " sessioncount " + sessions.length);
         
         for (int i = 0; i < sessions.length; i++) {
             if (!sessions[i].isValid()) {
@@ -325,8 +324,8 @@ public class SimpleSessionManager implements UserSessionManager {
         }
         
         long timeEnd = System.currentTimeMillis();
-        if(log.isDebugEnabled())
-             log.debug("End expire sessions " + " processingTime " + 
+        if(log.isLoggable(Level.FINE))
+             log.fine("End expire sessions " + " processingTime " + 
                        (timeEnd - timeNow) + " expired sessions: " + expireHere);
         
         processingTime += ( timeEnd - timeNow );
diff --git a/modules/tomcat-lite/java/org/apache/tomcat/util/http/HttpRequest.java b/modules/tomcat-lite/java/org/apache/tomcat/util/http/HttpRequest.java
new file mode 100644 (file)
index 0000000..7ed180d
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ */
+package org.apache.tomcat.util.http;
+
+import org.apache.tomcat.util.buf.MessageBytes;
+import org.apache.tomcat.util.buf.UDecoder;
+
+/**
+ * Simple request representation, public fields - no I/O or actions,
+ * just a struct.
+ * 
+ * Based on Coyote request.
+ * 
+ * @author Costin Manolache
+ */
+public class HttpRequest {
+    
+    // Same fields as in coyote - this is the primary info from request
+    
+    protected MessageBytes schemeMB;
+    
+    protected MessageBytes methodMB;
+    protected MessageBytes unparsedURIMB;
+    protected MessageBytes protoMB;
+    protected MimeHeaders headers;
+    
+    // Reference to 'real' request object
+    public Object nativeRequest;
+    public Object wrapperRequest;
+
+    protected MessageBytes remoteAddrMB;
+    protected MessageBytes remoteHostMB;
+    protected int remotePort;
+
+    protected MessageBytes localNameMB;
+    protected MessageBytes localAddrMB;
+    protected int localPort;
+
+    protected MessageBytes serverNameMB;
+    protected int serverPort = -1;
+    
+    public HttpRequest() {
+        schemeMB = 
+            MessageBytes.newInstance();
+        methodMB = MessageBytes.newInstance();
+        unparsedURIMB = MessageBytes.newInstance();
+        decodedUriMB = MessageBytes.newInstance();
+        requestURI = MessageBytes.newInstance();
+        protoMB = MessageBytes.newInstance();
+        headers = new MimeHeaders();
+        queryMB = MessageBytes.newInstance();
+        serverNameMB = MessageBytes.newInstance();
+        
+        parameters = new Parameters();
+        parameters.setQuery(queryMB);
+        parameters.setURLDecoder(urlDecoder);
+        //parameters.setHeaders(headers);
+        cookies = new Cookies(headers);
+        
+        initRemote();
+    }
+    
+    private void initRemote() {
+        remoteAddrMB = MessageBytes.newInstance();
+        localNameMB = MessageBytes.newInstance();
+        remoteHostMB = MessageBytes.newInstance();
+        localAddrMB = MessageBytes.newInstance();
+    }
+    
+    
+    public HttpRequest(MessageBytes scheme, MessageBytes method,
+            MessageBytes unparsedURI, MessageBytes protocol,
+            MimeHeaders mimeHeaders,
+            MessageBytes requestURI, 
+            MessageBytes decodedURI, 
+            MessageBytes query, Parameters params, 
+            MessageBytes serverName,
+            Cookies cookies) {
+        this.schemeMB = scheme;
+        this.methodMB = method;
+        this.unparsedURIMB = unparsedURI;
+        this.protoMB = protocol;
+        this.headers = mimeHeaders;
+        
+        this.requestURI = requestURI;
+        this.decodedUriMB = decodedURI;
+        this.queryMB = query;
+        this.parameters = params;
+        this.serverNameMB = serverName;
+        this.cookies = cookies;
+        initRemote();        
+    }
+
+
+    
+    // ==== Derived fields, computed after request is received ===
+    
+    protected MessageBytes requestURI;
+    protected MessageBytes queryMB;
+    protected MessageBytes decodedUriMB;
+    
+    // -----------------
+    protected Parameters parameters;
+    
+    protected MessageBytes contentTypeMB;
+
+    protected String charEncoding;
+    protected long contentLength = -1;
+
+    protected Cookies cookies;
+
+    // Avoid object creation:
+    protected UDecoder urlDecoder = new UDecoder();
+
+    
+    public void recycle() {
+        schemeMB.recycle();
+        methodMB.setString("GET");
+        unparsedURIMB.recycle();
+        protoMB.setString("HTTP/1.1");
+        headers.recycle();
+        
+        requestURI.recycle();
+        queryMB.recycle();
+        decodedUriMB.recycle();
+        
+        parameters.recycle();
+        contentTypeMB = null;
+        charEncoding = null;
+        contentLength = -1;
+        remoteAddrMB.recycle();
+        remoteHostMB.recycle();
+        cookies.recycle();
+    }
+    
+    public Parameters getParameters() {
+        return parameters;
+    }
+    
+    // For compatibility with coyote
+    public MessageBytes decodedURI() {
+        return decodedUriMB;
+    }
+
+    public MessageBytes requestURI() {
+        return requestURI;
+    }
+
+    public MessageBytes method() {
+        return methodMB;
+    }
+    
+    public String getHeader(String name) {
+        return headers.getHeader(name);
+    }
+
+    public MimeHeaders getMimeHeaders() {
+        return headers;
+    }
+    
+    /**
+     * Get the character encoding used for this request.
+     */
+    public String getCharacterEncoding() {
+
+        if (charEncoding != null)
+            return charEncoding;
+
+        charEncoding = ContentType.getCharsetFromContentType(getContentType());
+        return charEncoding;
+
+    }
+
+
+    public void setCharacterEncoding(String enc) {
+        this.charEncoding = enc;
+    }
+
+
+    public void setContentLength(int len) {
+        this.contentLength = len;
+    }
+
+
+    public int getContentLength() {
+        long length = getContentLengthLong();
+
+        if (length < Integer.MAX_VALUE) {
+            return (int) length;
+        }
+        return -1;
+    }
+
+    public long getContentLengthLong() {
+        if( contentLength > -1 ) return contentLength;
+
+        MessageBytes clB = headers.getUniqueValue("content-length");
+        contentLength = (clB == null || clB.isNull()) ? -1 : clB.getLong();
+
+        return contentLength;
+    }
+
+    public String getContentType() {
+        contentType();
+        if ((contentTypeMB == null) || contentTypeMB.isNull()) 
+            return null;
+        return contentTypeMB.toString();
+    }
+
+
+    public void setContentType(String type) {
+        contentTypeMB.setString(type);
+    }
+
+
+    public MessageBytes contentType() {
+        if (contentTypeMB == null || contentTypeMB.isNull())
+            contentTypeMB = headers.getValue("content-type");
+        return contentTypeMB;
+    }
+
+    public int getServerPort() {
+        return serverPort;
+    }
+    
+    public void setServerPort(int serverPort ) {
+        this.serverPort=serverPort;
+    }
+
+    public MessageBytes remoteAddr() {
+        return remoteAddrMB;
+    }
+
+    public MessageBytes remoteHost() {
+        return remoteHostMB;
+    }
+
+    public MessageBytes localName() {
+        return localNameMB;
+    }    
+
+    public MessageBytes localAddr() {
+        return localAddrMB;
+    }
+    
+    public int getRemotePort(){
+        return remotePort;
+    }
+        
+    public void setRemotePort(int port){
+        this.remotePort = port;
+    }
+    
+    public int getLocalPort(){
+        return localPort;
+    }
+        
+    public void setLocalPort(int port){
+        this.localPort = port;
+    }
+    
+    public MessageBytes queryString() {
+        return queryMB;
+    }
+    
+    public MessageBytes protocol() {
+        return protoMB;
+    }
+    
+    public MessageBytes scheme() {
+        return schemeMB;
+    }
+    
+    public MessageBytes serverName() {
+        return serverNameMB;
+    }
+
+    public MessageBytes unparsedURI() {
+        return unparsedURIMB;
+    }
+
+    public Cookies getCookies() {
+        return cookies;
+    }
+    
+    public UDecoder getURLDecoder() {
+        return urlDecoder;
+    }
+
+}
+
diff --git a/modules/tomcat-lite/java/org/apache/tomcat/util/http/HttpResponse.java b/modules/tomcat-lite/java/org/apache/tomcat/util/http/HttpResponse.java
new file mode 100644 (file)
index 0000000..1bcef50
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ */
+package org.apache.tomcat.util.http;
+
+import org.apache.tomcat.util.buf.MessageBytes;
+
+/**
+ * The data fields in a HTTP response and few helper and accessors.
+ * No actions - just a struct.
+ * 
+ * Subset of coyte response.
+ * 
+ * @author Costin Manolache
+ */
+public class HttpResponse {
+    // Primary fields 
+    // in coyote message is String, status is int
+    protected MessageBytes message = MessageBytes.newInstance();
+    protected MessageBytes proto = MessageBytes.newInstance();
+    protected MessageBytes statusBuffer = MessageBytes.newInstance();
+    protected MimeHeaders headers = new MimeHeaders();
+    public Object nativeResponse;
+       
+    boolean commited;
+    
+    public void recycle() {
+        getMimeHeaders().recycle();
+        message.recycle();
+        statusBuffer.setInt(200);
+        commited = false;
+    }
+    
+    public boolean isCommitted() {
+        return commited;
+    }
+
+    public void setCommitted(boolean b) {
+        commited = b;
+    }
+    
+    // Methods named for compat with coyote
+    
+    public void setStatus(int i) {
+        statusBuffer.setInt(i);
+    }
+    
+    public void setMessage(String s) {
+        message.setString(s);
+    }
+    
+    public String getMessage() {
+        return message.toString();
+    }
+    
+    public MessageBytes getMessageBuffer() {
+        return message;
+    }
+    
+    public MessageBytes protocol() {
+        return proto;
+    }
+    
+    public int getStatus() {
+        return statusBuffer.getInt();
+    }
+
+    public MessageBytes getStatusBuffer() {
+        return statusBuffer;
+    }
+    
+
+    public void addHeader(String name, String value) {
+        getMimeHeaders().addValue(name).setString(value);
+    }
+
+    public void setHeader(String name, String value) {
+        getMimeHeaders().setValue(name).setString(value);
+    }
+
+    public void setMimeHeaders(MimeHeaders resHeaders) {
+        this.headers = resHeaders;
+    }
+
+    public MimeHeaders getMimeHeaders() {
+        return headers;
+    }
+    
+    /**
+     * Warning: This method always returns <code>false<code> for Content-Type
+     * and Content-Length.
+     */
+    public boolean containsHeader(String name) {
+        return headers.getHeader(name) != null;
+    }
+
+    public void setContentLength(long length) {
+        MessageBytes clB = getMimeHeaders().getUniqueValue("content-length");
+        if (clB == null) {
+            clB = getMimeHeaders().addValue("content-length");
+        }        
+        clB.setLong(length);
+    }
+    
+    public long getContentLength() {
+        MessageBytes clB = getMimeHeaders().getUniqueValue("content-length");
+        return (clB == null || clB.isNull()) ? -1 : clB.getLong();
+    }
+    
+    public void setContentType(String contentType) {
+        MessageBytes clB = getMimeHeaders().getUniqueValue("content-type");
+        if (clB == null) {
+            setHeader("content-type", contentType);
+        } else {
+            clB.setString(contentType);
+        }
+    }
+    
+}
\ No newline at end of file
diff --git a/modules/tomcat-lite/java/org/apache/tomcat/util/http/MimeMap.java b/modules/tomcat-lite/java/org/apache/tomcat/util/http/MimeMap.java
new file mode 100644 (file)
index 0000000..07dbe02
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ *  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.util.http;
+
+import java.net.*;
+import java.util.*;
+
+
+/**
+ * A mime type map that implements the java.net.FileNameMap interface.
+ *
+ * @author James Duncan Davidson [duncan@eng.sun.com]
+ * @author Jason Hunter [jch@eng.sun.com]
+ */
+public class MimeMap implements FileNameMap {
+
+    // Defaults - all of them are "well-known" types,
+    // you can add using normal web.xml.
+    
+    public static Hashtable<String,String> defaultMap =
+        new Hashtable<String,String>(101);
+    static {
+        defaultMap.put("txt", "text/plain");
+        defaultMap.put("css", "text/css");
+        defaultMap.put("html","text/html");
+        defaultMap.put("htm", "text/html");
+        defaultMap.put("gif", "image/gif");
+        defaultMap.put("jpg", "image/jpeg");
+        defaultMap.put("jpe", "image/jpeg");
+        defaultMap.put("jpeg", "image/jpeg");
+        defaultMap.put("png", "image/png");
+                defaultMap.put("java", "text/plain");
+        defaultMap.put("body", "text/html");
+        defaultMap.put("rtx", "text/richtext");
+        defaultMap.put("tsv", "text/tab-separated-values");
+        defaultMap.put("etx", "text/x-setext");
+        defaultMap.put("ps", "application/x-postscript");
+        defaultMap.put("class", "application/java");
+        defaultMap.put("csh", "application/x-csh");
+        defaultMap.put("sh", "application/x-sh");
+        defaultMap.put("tcl", "application/x-tcl");
+        defaultMap.put("tex", "application/x-tex");
+        defaultMap.put("texinfo", "application/x-texinfo");
+        defaultMap.put("texi", "application/x-texinfo");
+        defaultMap.put("t", "application/x-troff");
+        defaultMap.put("tr", "application/x-troff");
+        defaultMap.put("roff", "application/x-troff");
+        defaultMap.put("man", "application/x-troff-man");
+        defaultMap.put("me", "application/x-troff-me");
+        defaultMap.put("ms", "application/x-wais-source");
+        defaultMap.put("src", "application/x-wais-source");
+        defaultMap.put("zip", "application/zip");
+        defaultMap.put("bcpio", "application/x-bcpio");
+        defaultMap.put("cpio", "application/x-cpio");
+        defaultMap.put("gtar", "application/x-gtar");
+        defaultMap.put("shar", "application/x-shar");
+        defaultMap.put("sv4cpio", "application/x-sv4cpio");
+        defaultMap.put("sv4crc", "application/x-sv4crc");
+        defaultMap.put("tar", "application/x-tar");
+        defaultMap.put("ustar", "application/x-ustar");
+        defaultMap.put("dvi", "application/x-dvi");
+        defaultMap.put("hdf", "application/x-hdf");
+        defaultMap.put("latex", "application/x-latex");
+        defaultMap.put("bin", "application/octet-stream");
+        defaultMap.put("oda", "application/oda");
+        defaultMap.put("pdf", "application/pdf");
+        defaultMap.put("ps", "application/postscript");
+        defaultMap.put("eps", "application/postscript");
+        defaultMap.put("ai", "application/postscript");
+        defaultMap.put("rtf", "application/rtf");
+        defaultMap.put("nc", "application/x-netcdf");
+        defaultMap.put("cdf", "application/x-netcdf");
+        defaultMap.put("cer", "application/x-x509-ca-cert");
+        defaultMap.put("exe", "application/octet-stream");
+        defaultMap.put("gz", "application/x-gzip");
+        defaultMap.put("Z", "application/x-compress");
+        defaultMap.put("z", "application/x-compress");
+        defaultMap.put("hqx", "application/mac-binhex40");
+        defaultMap.put("mif", "application/x-mif");
+        defaultMap.put("ief", "image/ief");
+        defaultMap.put("tiff", "image/tiff");
+        defaultMap.put("tif", "image/tiff");
+        defaultMap.put("ras", "image/x-cmu-raster");
+        defaultMap.put("pnm", "image/x-portable-anymap");
+        defaultMap.put("pbm", "image/x-portable-bitmap");
+        defaultMap.put("pgm", "image/x-portable-graymap");
+        defaultMap.put("ppm", "image/x-portable-pixmap");
+        defaultMap.put("rgb", "image/x-rgb");
+        defaultMap.put("xbm", "image/x-xbitmap");
+        defaultMap.put("xpm", "image/x-xpixmap");
+        defaultMap.put("xwd", "image/x-xwindowdump");
+        defaultMap.put("au", "audio/basic");
+        defaultMap.put("snd", "audio/basic");
+        defaultMap.put("aif", "audio/x-aiff");
+        defaultMap.put("aiff", "audio/x-aiff");
+        defaultMap.put("aifc", "audio/x-aiff");
+        defaultMap.put("wav", "audio/x-wav");
+        defaultMap.put("mpeg", "video/mpeg");
+        defaultMap.put("mpg", "video/mpeg");
+        defaultMap.put("mpe", "video/mpeg");
+        defaultMap.put("qt", "video/quicktime");
+        defaultMap.put("mov", "video/quicktime");
+        defaultMap.put("avi", "video/x-msvideo");
+        defaultMap.put("movie", "video/x-sgi-movie");
+        defaultMap.put("avx", "video/x-rad-screenplay");
+        defaultMap.put("wrl", "x-world/x-vrml");
+        defaultMap.put("mpv2", "video/mpeg2");
+        
+        /* Add XML related MIMEs */
+        
+        defaultMap.put("xml", "text/xml");
+        defaultMap.put("xsl", "text/xml");        
+        defaultMap.put("svg", "image/svg+xml");
+        defaultMap.put("svgz", "image/svg+xml");
+        defaultMap.put("wbmp", "image/vnd.wap.wbmp");
+        defaultMap.put("wml", "text/vnd.wap.wml");
+        defaultMap.put("wmlc", "application/vnd.wap.wmlc");
+        defaultMap.put("wmls", "text/vnd.wap.wmlscript");
+        defaultMap.put("wmlscriptc", "application/vnd.wap.wmlscriptc");
+    }
+    
+
+    private Hashtable<String,String> map = new Hashtable<String,String>();
+
+    public void addContentType(String extn, String type) {
+        map.put(extn, type.toLowerCase());
+    }
+
+    public Enumeration getExtensions() {
+        return map.keys();
+    }
+
+    public String getMimeType(String ext) {
+        return getContentTypeFor(ext);
+    }
+    
+    public String getContentType(String extn) {
+        String type = (String)map.get(extn.toLowerCase());
+        if( type == null ) type=(String)defaultMap.get( extn );
+        return type;
+    }
+
+    public void removeContentType(String extn) {
+        map.remove(extn.toLowerCase());
+    }
+
+    /** Get extension of file, without fragment id
+     */
+    public static String getExtension( String fileName ) {
+        // play it safe and get rid of any fragment id
+        // that might be there
+        int length=fileName.length();
+        
+        int newEnd = fileName.lastIndexOf('#');
+        if( newEnd== -1 ) newEnd=length;
+        // Instead of creating a new string.
+        //         if (i != -1) {
+        //             fileName = fileName.substring(0, i);
+        //         }
+        int i = fileName.lastIndexOf('.', newEnd );
+        if (i != -1) {
+             return  fileName.substring(i + 1, newEnd );
+        } else {
+            // no extension, no content type
+            return null;
+        }
+    }
+    
+    public String getContentTypeFor(String fileName) {
+        String extn=getExtension( fileName );
+        if (extn!=null) {
+            return getContentType(extn);
+        } else {
+            // no extension, no content type
+            return null;
+        }
+    }
+
+}
index 7c1adc3..6e63233 100644 (file)
 package org.apache.tomcat.util.http.mapper;
 
 
-import org.apache.tomcat.util.buf.CharChunk;
-import org.apache.tomcat.util.buf.MessageBytes;
-import org.apache.tomcat.util.buf.Ascii;
-
 import java.io.File;
 import java.io.IOException;
-import java.util.List;
 import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.tomcat.util.buf.Ascii;
+import org.apache.tomcat.util.buf.CharChunk;
+import org.apache.tomcat.util.buf.MessageBytes;
 
 /**
  * Mapper, which implements the servlet API mapping rules (which are derived