tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cos...@apache.org
Subject svn commit: r761964 [6/10] - in /tomcat/trunk/modules/tomcat-lite/java: ./ org/ org/apache/ org/apache/tomcat/ org/apache/tomcat/addons/ org/apache/tomcat/integration/ org/apache/tomcat/integration/jmx/ org/apache/tomcat/integration/simple/ org/apache/...
Date Sat, 04 Apr 2009 16:24:36 GMT
Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/CoyoteHttp.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/CoyoteHttp.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/CoyoteHttp.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/coyote/CoyoteHttp.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,174 @@
+/*
+ */
+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);
+    }
+
+
+    
+}

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

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

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

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

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

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

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

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

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

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

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

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/webxml/TomcatLiteWebXmlConfig.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/webxml/TomcatLiteWebXmlConfig.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/webxml/TomcatLiteWebXmlConfig.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/webxml/TomcatLiteWebXmlConfig.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,64 @@
+/*
+ */
+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;
+
+/**
+ * Default configurator - parse web.xml, init the context.
+ * 
+ * Will be executed first - if set as the default config addon.
+ * 
+ * Possible extensions: 
+ *   - read from a .ser file instead of web.xml
+ *   - custom code for manual/extra config
+ *   - read from a central repo
+ *  
+ * @author Costin Manolache
+ */
+public class TomcatLiteWebXmlConfig implements ContextPreinitListener {
+
+    protected void readWebXml(ServletContextImpl ctx, 
+                              String base) throws ServletException {
+        // TODO: .ser, reloading, etc
+//        if (contextConfig != null && contextConfig.fileName != null) {
+//            // TODO: this should move to deploy - if not set, there is no point
+//            File f = new File(contextConfig.fileName);
+//            if (f.exists()) {
+//                if (f.lastModified() > contextConfig.timestamp + 1000) {
+//                    log("Reloading web.xml");
+//                    contextConfig = null;
+//                }
+//            } else {
+//                log("Old web.xml");
+//                contextConfig = null;
+//            }
+//        }
+        if (base != null) {
+            WebXml webXml = new WebXml(ctx.getContextConfig());
+            webXml.readWebXml(base);
+        }
+    }
+
+    @Override
+    public void preInit(ServletContext ctx) {
+        ServletContextImpl servletContext =  
+            (ServletContextImpl) ctx;
+        
+        String base = servletContext.getBasePath();
+        if (base == null) {
+            return; // nothing we can do
+        }
+        try {
+            readWebXml(servletContext, base);
+        } catch (ServletException e) {
+            // TODO Auto-generated catch block
+            throw new RuntimeException(e);
+        }
+    }
+    
+}

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

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/webxml/WebAnnotation.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/webxml/WebAnnotation.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/webxml/WebAnnotation.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/webxml/WebAnnotation.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,152 @@
+package org.apache.tomcat.lite.webxml;
+
+import java.util.Iterator;
+import java.util.List;
+
+import javax.annotation.security.DeclareRoles;
+import javax.annotation.security.RunAs;
+
+import org.apache.tomcat.lite.ServletContextConfig;
+import org.apache.tomcat.lite.ServletContextConfig.FilterData;
+import org.apache.tomcat.lite.ServletContextConfig.ServletData;
+
+
+
+
+/**
+ * Based on catalina.WebAnnotationSet
+ * 
+ * Supports:
+ *  @DeclaresRoles - on Servlet class - web-app/security-role/role-name
+ *  @RunAs - on Servlet class - web-app/servlet/run-as
+ *  
+ * 
+ * No support for jndi @Resources, @Resource
+ * No @InjectionComplete callback annotation
+ * 
+ * No support for @EJB, @WebServiceRef
+ *  
+ * @author costin
+ * @author Fabien Carrion
+ */
+public class WebAnnotation {
+
+    /**
+     * Process the annotations on a context.
+     */
+    public static void loadApplicationAnnotations(ServletContextConfig context, ClassLoader classLoader) {
+        loadApplicationListenerAnnotations(context, classLoader);
+        loadApplicationFilterAnnotations(context, classLoader);
+        loadApplicationServletAnnotations(context, classLoader);
+    }
+    
+    
+    // -------------------------------------------------------- protected Methods
+    
+    
+    /**
+     * Process the annotations for the listeners.
+     */
+    static void loadApplicationListenerAnnotations(ServletContextConfig context, ClassLoader classLoader) {
+        List applicationListeners = context.listenerClass;
+        for (int i = 0; i < applicationListeners.size(); i++) {
+            loadClassAnnotation(context, (String)applicationListeners.get(i), classLoader);
+        }
+    }
+    
+    
+    /**
+     * Process the annotations for the filters.
+     */
+    static void loadApplicationFilterAnnotations(ServletContextConfig context, ClassLoader classLoader) {
+        Iterator i1 = context.filters.values().iterator();
+        while (i1.hasNext()) {
+            FilterData fc = (FilterData) i1.next();
+            loadClassAnnotation(context, fc.filterClass, classLoader);
+        }
+    }
+    
+    
+    /**
+     * Process the annotations for the servlets.
+     * @param classLoader 
+     */
+    static void loadApplicationServletAnnotations(ServletContextConfig context, ClassLoader classLoader) {
+        Class classClass = null;
+        
+        
+        Iterator i1 = context.servlets.values().iterator();
+        while (i1.hasNext()) {
+            ServletData sd = (ServletData) i1.next();
+            if (sd.servletClass == null) {
+                continue;
+            }
+
+            try {
+                classClass = classLoader.loadClass(sd.servletClass);
+            } catch (ClassNotFoundException e) {
+                // We do nothing
+            } catch (NoClassDefFoundError e) {
+                // We do nothing
+            }
+
+            if (classClass == null) {
+                continue;
+            }
+
+            loadClassAnnotation(context, classClass);
+            /* Process RunAs annotation which can be only on servlets.
+             * Ref JSR 250, equivalent to the run-as element in
+             * the deployment descriptor
+             */
+            if (classClass.isAnnotationPresent(RunAs.class)) {
+                RunAs annotation = (RunAs) 
+                classClass.getAnnotation(RunAs.class);
+                sd.runAs = annotation.value();
+            }
+        }
+    }
+    
+    /**
+     * Process the annotations on a context for a given className.
+     */
+    static void loadClassAnnotation(ServletContextConfig context, 
+                                    String classClass2, ClassLoader classLoader) {
+        
+        Class classClass = null;
+        
+        try {
+            classClass = classLoader.loadClass(classClass2);
+        } catch (ClassNotFoundException e) {
+            // We do nothing
+        } catch (NoClassDefFoundError e) {
+            // We do nothing
+        }
+        
+        if (classClass == null) {
+            return;
+        }
+        loadClassAnnotation(context, classClass);
+    }
+     
+    static void loadClassAnnotation(ServletContextConfig context, 
+                                    Class classClass) {
+        
+        /* Process DeclareRoles annotation.
+         * Ref JSR 250, equivalent to the security-role element in
+         * the deployment descriptor
+         */
+        if (classClass.isAnnotationPresent(DeclareRoles.class)) {
+            DeclareRoles annotation = (DeclareRoles) 
+                classClass.getAnnotation(DeclareRoles.class);
+            for (int i = 0; annotation.value() != null && 
+                            i < annotation.value().length; i++) {
+                context.securityRole.add(annotation.value()[i]);
+            }
+        }
+        
+        
+    }
+
+    
+}

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

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/webxml/WebResourceCollectionData.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/webxml/WebResourceCollectionData.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/webxml/WebResourceCollectionData.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/webxml/WebResourceCollectionData.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,13 @@
+/**
+ * 
+ */
+package org.apache.tomcat.lite.webxml;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+
+public class WebResourceCollectionData implements Serializable {
+    public String webResourceName;
+    public ArrayList urlPattern = new ArrayList();
+    public ArrayList httpMethod = new ArrayList();
+}
\ No newline at end of file

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

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/webxml/WebXml.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/webxml/WebXml.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/webxml/WebXml.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/lite/webxml/WebXml.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,384 @@
+/*
+ */
+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;
+
+import javax.servlet.ServletException;
+
+import org.apache.tomcat.lite.ServletContextConfig;
+import org.apache.tomcat.lite.ServletContextConfig.EnvEntryData;
+import org.apache.tomcat.lite.ServletContextConfig.FilterData;
+import org.apache.tomcat.lite.ServletContextConfig.FilterMappingData;
+import org.apache.tomcat.lite.ServletContextConfig.SecurityConstraintData;
+import org.apache.tomcat.lite.ServletContextConfig.ServletData;
+import org.apache.tomcat.util.DomUtil;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/** 
+ * General-purpose utility to process an web.xml file. Result
+ *  is a tree of objects starting with WebAppData.
+ * 
+ * TODO: allow writting of web.xml, allow modification ( preserving 
+ * comments )
+ * 
+ * @author costin
+ */
+public class WebXml {
+    ServletContextConfig d;
+    
+    public WebXml(ServletContextConfig cfg) {
+        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;
+    }
+    
+    public void readWebXml(String baseDir) throws ServletException {
+        try {
+            File webXmlFile = new File( baseDir + "/WEB-INF/web.xml");
+            if (!webXmlFile.exists()) {
+                return;
+            }
+            d.fileName = webXmlFile.getCanonicalPath();
+            d.timestamp = webXmlFile.lastModified();
+            
+            FileInputStream fileInputStream = new FileInputStream(webXmlFile);
+            readWebXml(fileInputStream);
+        } catch (Exception e) {
+            e.printStackTrace();
+            throw new ServletException(e);
+        }
+    }
+    
+     public void readWebXml(InputStream fileInputStream) 
+             throws ServletException {
+         try {
+                    
+            Document document = DomUtil.readXml(fileInputStream);
+            Node webappNode = DomUtil.getChild(document, "web-app");
+
+            String fullS = DomUtil.getAttribute(webappNode, "full");
+            if (fullS != null && fullS.equalsIgnoreCase("true")) {
+                d.full = true;
+            }
+            
+            d.displayName = DomUtil.getAttribute(webappNode, "display-name");
+                        
+            // Process each child of web-app
+            Node confNode = DomUtil.getChild(webappNode, "filter");
+            while (confNode != null ) {
+                processFilter(confNode);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "filter-mapping");
+            while (confNode != null ) {
+                processFilterMapping(confNode);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "context-param");
+            while (confNode != null ) {
+                String n = DomUtil.getChildContent(confNode, "param-name").trim();
+                String v = DomUtil.getChildContent(confNode, "param-value").trim();
+                d.contextParam.put(n, v);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "mime-mapping");
+            while (confNode != null ) {
+                String n = DomUtil.getChildContent(confNode, "extension");
+                String t = DomUtil.getChildContent(confNode, "mime-type");
+                d.mimeMapping.put(n, t);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "error-page");
+            while (confNode != null ) {
+                processErrorPage(confNode);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "jsp-config");
+            while (confNode != null ) {
+                processJspConfig(confNode);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "servlet");
+            while (confNode != null ) {
+                processServlet(confNode);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "servlet-mapping");
+            while (confNode != null ) {
+                processServletMapping(confNode);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "listener");
+            while (confNode != null ) {
+                String lClass = DomUtil.getChildContent(confNode, "listener-class");
+                d.listenerClass.add(lClass);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "security-constraint");
+            while (confNode != null ) {
+                processSecurityConstraint(confNode);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "login-config");
+            while (confNode != null ) {
+                processLoginConfig(confNode);
+                confNode = DomUtil.getNext(confNode);
+                if (confNode != null) 
+                    throw new ServletException("Multiple login-config");
+            }
+
+            confNode = DomUtil.getChild(webappNode, "session-config");
+            while (confNode != null ) {
+                String n = DomUtil.getChildContent(confNode, "session-timeout");
+                int stout = Integer.parseInt(n);
+                d.sessionTimeout = stout;
+                confNode = DomUtil.getNext(confNode);
+                if (confNode != null) 
+                    throw new ServletException("Multiple session-config");
+            }
+
+            confNode = DomUtil.getChild(webappNode, "welcome-file-list");
+            while (confNode != null ) {
+                Node wf = DomUtil.getChild(confNode, "welcome-file");
+                while (wf != null) {
+                    String file = DomUtil.getContent(wf);
+                    d.welcomeFileList.add(file);
+                    wf = DomUtil.getNext(wf);
+                }
+                // more sections ?
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            // Not supported right now - TODO: collect, have jndi plugin
+            confNode = DomUtil.getChild(webappNode, "env-entry");
+            while (confNode != null ) {
+                processEnvEntry(confNode);
+                confNode = DomUtil.getNext(confNode);
+            }
+            
+            confNode = DomUtil.getChild(webappNode, "locale-encoding-mapping-list");
+            while (confNode != null ) {
+                confNode = DomUtil.getNext(confNode);
+                String n = DomUtil.getChildContent(confNode, "locale");
+                String t = DomUtil.getChildContent(confNode, "encoding");
+                d.localeEncodingMapping.put(n, t);
+            }
+
+            confNode = DomUtil.getChild(webappNode, "distributable");
+            while (confNode != null ) {
+                d.distributable = true;
+                confNode = DomUtil.getNext(confNode);
+            }
+
+            confNode = DomUtil.getChild(confNode, "security-role");
+            while (confNode != null ) {
+                String n = DomUtil.getChildContent(confNode, "role-name");
+                d.securityRole.add(n);
+                confNode = DomUtil.getNext(confNode);
+            }
+
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    throw new ServletException(e);
+                }
+    }
+    
+    private void processJspConfig(Node confNode) {
+        Node tagLib = DomUtil.getChild(confNode, "taglib");
+        while (tagLib != null) {
+            String uri = DomUtil.getChildContent(tagLib, "taglib-uri");
+            String l = DomUtil.getChildContent(tagLib, "taglib-location");
+            //d.tagLibs.put(uri, l);
+            tagLib = DomUtil.getNext(tagLib);
+        }
+        
+        tagLib = DomUtil.getChild(confNode, "jsp-property-group");
+        while (tagLib != null) {
+            // That would be the job of the JSP servlet to process.
+            tagLib = DomUtil.getNext(tagLib);
+        }
+    }
+
+    private void processEnvEntry(Node confNode) {
+        EnvEntryData ed = new EnvEntryData();
+        ed.envEntryName = DomUtil.getChildContent(confNode,"env-entry-name");
+        ed.envEntryType = DomUtil.getChildContent(confNode,"env-entry-type");
+        ed.envEntryValue = DomUtil.getChildContent(confNode,"env-entry-value");
+        d.envEntry.add(ed);
+    }
+
+    private void processLoginConfig(Node confNode) {
+        d.authMethod = DomUtil.getChildContent(confNode,"auth-method");
+        d.realmName = DomUtil.getChildContent(confNode,"auth-method");
+        Node formNode = DomUtil.getChild(confNode, "form-login-config");
+        if (formNode != null) {
+            d.formLoginPage = DomUtil.getChildContent(formNode,"form-login-page");
+            d.formErrorPage = DomUtil.getChildContent(formNode,"form-error-page");
+        }
+    }
+
+    private void processSecurityConstraint(Node confNode) {
+        SecurityConstraintData sd = new SecurityConstraintData();
+        Node cn = DomUtil.getChild(confNode, "web-resource-collection");
+        while (cn != null) {
+            WebResourceCollectionData wrd = new WebResourceCollectionData();
+            wrd.webResourceName = DomUtil.getChildContent(cn, "web-resource-name");
+            Node scn = DomUtil.getChild(cn,"url-pattern");
+            while (scn != null) {
+                wrd.urlPattern.add(DomUtil.getContent(scn));
+                scn = DomUtil.getNext(scn);
+            }
+            scn = DomUtil.getChild(cn,"http-method");
+            while (scn != null) {
+                wrd.httpMethod.add(DomUtil.getContent(scn));
+                scn = DomUtil.getNext(scn);
+            }
+            cn = DomUtil.getNext(cn);
+        }
+        d.securityConstraint.add(sd);
+    }
+
+    private void processErrorPage(Node confNode) {
+        String name = DomUtil.getChildContent(confNode,"location");
+        String c = DomUtil.getChildContent(confNode,"error-code");
+        String t = DomUtil.getChildContent(confNode,"exception-type");
+        if (c != null) {
+            d.errorPageCode.put(c, name);
+        }
+        if (t != null) {
+            d.errorPageException.put(t, name);
+        }
+    }
+
+    private void processServlet(Node confNode) throws ServletException {
+        ServletData sd = new ServletData();
+
+        sd.servletName = DomUtil.getChildContent(confNode,"servlet-name");
+        sd.servletClass = DomUtil.getChildContent(confNode,"servlet-class");
+        sd.jspFile = DomUtil.getChildContent(confNode,"jsp-file");
+        
+        processInitParams(confNode, sd.initParams);
+        
+        d.servlets.put( sd.servletName, sd );
+        
+        String los = DomUtil.getChildContent(confNode, "load-on-startup");
+        if (los != null ) { 
+            sd.loadOnStartup = Integer.parseInt(los);
+        }
+        
+        Node sn = DomUtil.getChild(confNode, "security-role-ref");
+        while (sn != null ) {
+            String roleName = DomUtil.getChildContent(sn, "role-name");
+            String roleLink = DomUtil.getChildContent(sn, "role-link");
+            if (roleLink == null) {
+                sd.securityRoleRef.put(roleName, "");
+            } else {
+                sd.securityRoleRef.put(roleName, roleLink);
+            }
+            sn = DomUtil.getNext(sn);
+        }
+    }
+
+    private void processInitParams(Node confNode, HashMap initParams) {
+        Node initN = DomUtil.getChild(confNode, "init-param");
+        while (initN != null ) {
+            String n = DomUtil.getChildContent(initN, "param-name");
+            String v = DomUtil.getChildContent(initN, "param-value");
+            initParams.put(n, v);
+            initN = DomUtil.getNext(initN);
+        }
+    }
+
+    private void processServletMapping(Node confNode) {
+        String name = DomUtil.getChildContent(confNode,"servlet-name");
+        Node dataN = DomUtil.getChild(confNode, "url-pattern");
+        while (dataN != null) {
+            String path = DomUtil.getContent(dataN).trim();
+            dataN = DomUtil.getNext(dataN);
+            
+            if (! (path.startsWith("/") || path.startsWith("*"))) {
+                // backward compat 
+                path = "/" + path;
+            }
+            d.servletMapping.put(path, name);
+        }
+    }
+
+    private void processFilterMapping(Node confNode) {
+      String filterName = DomUtil.getChildContent(confNode,"filter-name");
+      // multiple 
+      ArrayList dispatchers = new ArrayList();
+      Node dataN = DomUtil.getChild(confNode, "dispatcher");
+      while (dataN != null ) {
+          String d = DomUtil.getContent(dataN);
+          dispatchers.add(d);
+          dataN = DomUtil.getNext(dataN);
+      }
+      
+      // Multiple url-pattern and servlet-name in one
+      // mapping rule. Need to be applied in order.
+      dataN = DomUtil.getChild(confNode, "url-pattern");
+      while (dataN != null ) {
+        FilterMappingData fm = new FilterMappingData();
+        fm.filterName = filterName;
+        fm.dispatcher = dispatchers;
+        String path = DomUtil.getContent(dataN);
+        dataN = DomUtil.getNext(dataN);
+        fm.urlPattern = path;
+        d.filterMappings.add(fm);
+      }
+      dataN = DomUtil.getChild(confNode, "servlet-name");
+      while (dataN != null ) {
+        FilterMappingData fm = new FilterMappingData();
+        fm.filterName = filterName;
+        fm.dispatcher = dispatchers;
+        String sn = DomUtil.getContent(dataN);
+        dataN = DomUtil.getNext(dataN);
+        fm.servletName = sn;
+        d.filterMappings.add(fm);
+      }
+    }
+
+    private void processFilter(Node confNode) {
+        String name = DomUtil.getChildContent(confNode,"filter-name");
+        String sclass = DomUtil.getChildContent(confNode,"filter-class");
+        
+        FilterData fd = new FilterData();
+        processInitParams(confNode, fd.initParams);
+        fd.filterName = name;
+        fd.filterClass = sclass;
+        d.filters.put(name, fd);
+    }
+    
+}

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

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/file/CopyUtils.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/file/CopyUtils.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/file/CopyUtils.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/file/CopyUtils.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,257 @@
+package org.apache.tomcat.servlets.file;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.Reader;
+
+import javax.servlet.ServletOutputStream;
+
+public class CopyUtils {
+    protected static int input = 2048;
+
+    /**
+     * Copy the contents of the specified input stream to the specified
+     * output stream, and ensure that both streams are closed before returning
+     * (even in the face of an exception).
+     *
+     * @param resourceInfo The resource info
+     * @param writer The writer to write to
+     *
+     * @exception IOException if an input/output error occurs
+     */
+    public static void copy(InputStream is, 
+                            PrintWriter writer,
+                            String fileEncoding)
+        throws IOException {
+
+        IOException exception = null;
+
+        InputStream resourceInputStream = is;
+
+        Reader reader;
+        if (fileEncoding == null) {
+            reader = new InputStreamReader(resourceInputStream);
+        } else {
+            reader = new InputStreamReader(resourceInputStream,
+                                           fileEncoding);
+        }
+
+        // Copy the input stream to the output stream
+        exception = copyRange(reader, writer);
+
+        // Clean up the reader
+        try {
+            reader.close();
+        } catch (Throwable t) {
+            ;
+        }
+
+        // Rethrow any exception that has occurred
+        if (exception != null)
+            throw exception;
+
+    }
+
+    /**
+     * Copy the contents of the specified input stream to the specified
+     * output stream, and ensure that both streams are closed before returning
+     * (even in the face of an exception).
+     *
+     * @param resourceInfo The resource information
+     * @param ostream The output stream to write to
+     *
+     * @exception IOException if an input/output error occurs
+     */
+    public static void copy(InputStream is, OutputStream ostream)
+            throws IOException {
+
+        IOException exception = null;
+        InputStream resourceInputStream = null;
+
+        resourceInputStream = is;
+
+        InputStream istream = new BufferedInputStream
+            (resourceInputStream, input);
+
+        // Copy the input stream to the output stream
+        exception = CopyUtils.copyRange(istream, ostream);
+
+        // Clean up the input stream
+        try {
+            istream.close();
+        } catch (Throwable t) {
+            ;
+        }
+
+        // Rethrow any exception that has occurred
+        if (exception != null)
+            throw exception;
+    }
+
+    /**
+     * Copy the contents of the specified input stream to the specified
+     * output stream, and ensure that both streams are closed before returning
+     * (even in the face of an exception).
+     *
+     * @param istream The input stream to read from
+     * @param ostream The output stream to write to
+     * @return Exception which occurred during processing
+     */
+    public static IOException copyRange(InputStream istream,
+                                        OutputStream ostream) {
+
+        // Copy the input stream to the output stream
+        IOException exception = null;
+        byte buffer[] = new byte[input];
+        int len = buffer.length;
+        while (true) {
+            try {
+                len = istream.read(buffer);
+                if (len == -1)
+                    break;
+                ostream.write(buffer, 0, len);
+            } catch (IOException e) {
+                exception = e;
+                len = -1;
+                break;
+            }
+        }
+        return exception;
+
+    }
+
+
+    /**
+     * Copy the contents of the specified input stream to the specified
+     * output stream, and ensure that both streams are closed before returning
+     * (even in the face of an exception).
+     *
+     * @param reader The reader to read from
+     * @param writer The writer to write to
+     * @return Exception which occurred during processing
+     */
+    public static IOException copyRange(Reader reader, PrintWriter writer) {
+
+        // Copy the input stream to the output stream
+        IOException exception = null;
+        char buffer[] = new char[input];
+        int len = buffer.length;
+        while (true) {
+            try {
+                len = reader.read(buffer);
+                if (len == -1)
+                    break;
+                writer.write(buffer, 0, len);
+            } catch (IOException e) {
+                exception = e;
+                len = -1;
+                break;
+            }
+        }
+        return exception;
+
+    }
+
+
+    /**
+     * Copy the contents of the specified input stream to the specified
+     * output stream, and ensure that both streams are closed before returning
+     * (even in the face of an exception).
+     *
+     * @param istream The input stream to read from
+     * @param ostream The output stream to write to
+     * @param start Start of the range which will be copied
+     * @param end End of the range which will be copied
+     * @return Exception which occurred during processing
+     */
+    public static IOException copyRange(InputStream istream,
+                                  ServletOutputStream ostream,
+                                  long start, long end) {
+
+        try {
+            istream.skip(start);
+        } catch (IOException e) {
+            return e;
+        }
+
+        IOException exception = null;
+        long bytesToRead = end - start + 1;
+
+        byte buffer[] = new byte[input];
+        int len = buffer.length;
+        while ( (bytesToRead > 0) && (len >= buffer.length)) {
+            try {
+                len = istream.read(buffer);
+                if (bytesToRead >= len) {
+                    ostream.write(buffer, 0, len);
+                    bytesToRead -= len;
+                } else {
+                    ostream.write(buffer, 0, (int) bytesToRead);
+                    bytesToRead = 0;
+                }
+            } catch (IOException e) {
+                exception = e;
+                len = -1;
+            }
+            if (len < buffer.length)
+                break;
+        }
+
+        return exception;
+
+    }
+
+
+
+    /**
+     * Copy the contents of the specified input stream to the specified
+     * output stream, and ensure that both streams are closed before returning
+     * (even in the face of an exception).
+     *
+     * @param reader The reader to read from
+     * @param writer The writer to write to
+     * @param start Start of the range which will be copied
+     * @param end End of the range which will be copied
+     * @return Exception which occurred during processing
+     */
+    public static IOException copyRange(Reader reader, PrintWriter writer,
+                                  long start, long end) {
+
+        try {
+            reader.skip(start);
+        } catch (IOException e) {
+            return e;
+        }
+
+        IOException exception = null;
+        long bytesToRead = end - start + 1;
+
+        char buffer[] = new char[input];
+        int len = buffer.length;
+        while ( (bytesToRead > 0) && (len >= buffer.length)) {
+            try {
+                len = reader.read(buffer);
+                if (bytesToRead >= len) {
+                    writer.write(buffer, 0, len);
+                    bytesToRead -= len;
+                } else {
+                    writer.write(buffer, 0, (int) bytesToRead);
+                    bytesToRead = 0;
+                }
+            } catch (IOException e) {
+                exception = e;
+                len = -1;
+            }
+            if (len < buffer.length)
+                break;
+        }
+
+        return exception;
+
+    }
+
+}

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



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


Mime
View raw message