You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by co...@locus.apache.org on 2000/05/23 22:58:30 UTC
cvs commit: jakarta-tomcat/src/share/org/apache/tomcat/util MessageString.java MimeHeaderField.java MimeHeaders.java
costin 00/05/23 13:58:28
Modified: src/share/org/apache/tomcat/context
LoadOnStartupInterceptor.java
src/share/org/apache/tomcat/core Context.java
ContextManager.java
src/share/org/apache/tomcat/facade
HttpServletRequestFacade.java
ServletContextFacade.java
src/share/org/apache/tomcat/service
Ajp11ConnectionHandler.java
src/share/org/apache/tomcat/service/connector
Ajp12ConnectionHandler.java
src/share/org/apache/tomcat/service/http
HttpResponseAdapter.java
src/share/org/apache/tomcat/util MessageString.java
MimeHeaderField.java MimeHeaders.java
Log:
- Fix Facade problem ( RequestDispatcher )
- start working on MimeHeader
- remove gross garbage generation in HttpResponse ( and Ajp11, Ajp12 adapters that extend it)
StringBuffer.setLength(0) is _wrong_
Note that the code is still bad - changing the I/O system to support other charsets and
avoid multiple buffers is probably the most important thing ( both I18N and performance).
Revision Changes Path
1.10 +1 -1 jakarta-tomcat/src/share/org/apache/tomcat/context/LoadOnStartupInterceptor.java
Index: LoadOnStartupInterceptor.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/context/LoadOnStartupInterceptor.java,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- LoadOnStartupInterceptor.java 2000/02/17 07:52:18 1.9
+++ LoadOnStartupInterceptor.java 2000/05/23 20:58:18 1.10
@@ -177,7 +177,7 @@
request.setContext(context);
request.getSession(true);
- RequestDispatcher rd = context.getRequestDispatcher(requestURI);
+ RequestDispatcher rd = context.getFacade().getRequestDispatcher(requestURI);
try {
rd.forward(request.getFacade(), response.getFacade());
1.88 +0 -25 jakarta-tomcat/src/share/org/apache/tomcat/core/Context.java
Index: Context.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Context.java,v
retrieving revision 1.87
retrieving revision 1.88
diff -u -r1.87 -r1.88
--- Context.java 2000/05/23 16:56:41 1.87
+++ Context.java 2000/05/23 20:58:21 1.88
@@ -730,31 +730,6 @@
// -------------------- Facade methods --------------------
- public RequestDispatcher getRequestDispatcher(String path) {
- if ( path == null || ! path.startsWith("/")) {
- return null; // spec say "return null if we can't return a dispather
- }
- RequestDispatcherImpl rD=new RequestDispatcherImpl( this );
- rD.setPath( path );
-
- return rD;
- }
-
- public RequestDispatcher getNamedDispatcher(String name) {
- if (name == null)
- return null;
-
- // We need to do the checks
- ServletWrapper wrapper = getServletByName( name );
- if (wrapper == null)
- return null;
- RequestDispatcherImpl rD=new RequestDispatcherImpl( this );
- rD.setName( name );
-
- return rD;
- }
-
-
public Context getContext(String path) {
if (! path.startsWith("/")) {
return null; // according to spec, null is returned
1.80 +1 -1 jakarta-tomcat/src/share/org/apache/tomcat/core/ContextManager.java
Index: ContextManager.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ContextManager.java,v
retrieving revision 1.79
retrieving revision 1.80
diff -u -r1.79 -r1.80
--- ContextManager.java 2000/05/23 16:56:42 1.79
+++ ContextManager.java 2000/05/23 20:58:21 1.80
@@ -832,7 +832,7 @@
// Try a normal "error page" ( path based )
if( errorServlet==null && errorPath != null ) {
try {
- RequestDispatcher rd = ctx.getRequestDispatcher(errorPath);
+ RequestDispatcher rd = ctx.getFacade().getRequestDispatcher(errorPath);
// reset the response, keeping the status code if necessary
// try a forward if possible, otherwise an include
if (res.isBufferCommitted()) {
1.2 +1 -1 jakarta-tomcat/src/share/org/apache/tomcat/facade/HttpServletRequestFacade.java
Index: HttpServletRequestFacade.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/facade/HttpServletRequestFacade.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- HttpServletRequestFacade.java 2000/05/23 16:56:51 1.1
+++ HttpServletRequestFacade.java 2000/05/23 20:58:22 1.2
@@ -288,7 +288,7 @@
if( path==null) return null;
}
- return request.getContext().getRequestDispatcher(path);
+ return request.getContext().getFacade().getRequestDispatcher(path);
}
/** Adapter: first elelment
1.2 +18 -2 jakarta-tomcat/src/share/org/apache/tomcat/facade/ServletContextFacade.java
Index: ServletContextFacade.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/facade/ServletContextFacade.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ServletContextFacade.java 2000/05/23 16:56:52 1.1
+++ ServletContextFacade.java 2000/05/23 20:58:22 1.2
@@ -150,11 +150,27 @@
}
public RequestDispatcher getRequestDispatcher(String path) {
- return context.getRequestDispatcher( path );
+ if ( path == null || ! path.startsWith("/")) {
+ return null; // spec say "return null if we can't return a dispather
+ }
+ RequestDispatcherImpl rD=new RequestDispatcherImpl( context );
+ rD.setPath( path );
+
+ return rD;
}
public RequestDispatcher getNamedDispatcher(String name) {
- return context.getNamedDispatcher( name );
+ if (name == null)
+ return null;
+
+ // We need to do the checks
+ ServletWrapper wrapper = context.getServletByName( name );
+ if (wrapper == null)
+ return null;
+ RequestDispatcherImpl rD=new RequestDispatcherImpl( context );
+ rD.setName( name );
+
+ return rD;
}
public String getServerInfo() {
1.18 +6 -6 jakarta-tomcat/src/share/org/apache/tomcat/service/Ajp11ConnectionHandler.java
Index: Ajp11ConnectionHandler.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/Ajp11ConnectionHandler.java,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- Ajp11ConnectionHandler.java 2000/04/25 17:54:20 1.17
+++ Ajp11ConnectionHandler.java 2000/05/23 20:58:23 1.18
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/Ajp11ConnectionHandler.java,v 1.17 2000/04/25 17:54:20 costin Exp $
- * $Revision: 1.17 $
- * $Date: 2000/04/25 17:54:20 $
+ * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/Ajp11ConnectionHandler.java,v 1.18 2000/05/23 20:58:23 costin Exp $
+ * $Revision: 1.18 $
+ * $Date: 2000/05/23 20:58:23 $
*
* ====================================================================
*
@@ -312,9 +312,9 @@
/** Override setStatus
*/
public void sendStatus( int status, String message) throws IOException {
- statusSB.setLength(0);
- statusSB.append("Status: " ).append( status ).append("\r\n");
- sout.write(statusSB.toString().getBytes());
+ printHead("Status: " );
+ printHead( String.valueOf( status ));
+ printHead("\r\n");
}
}
1.25 +5 -5 jakarta-tomcat/src/share/org/apache/tomcat/service/connector/Ajp12ConnectionHandler.java
Index: Ajp12ConnectionHandler.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/connector/Ajp12ConnectionHandler.java,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -r1.24 -r1.25
--- Ajp12ConnectionHandler.java 2000/04/25 17:54:23 1.24
+++ Ajp12ConnectionHandler.java 2000/05/23 20:58:24 1.25
@@ -496,11 +496,11 @@
/** Override setStatus
*/
protected void sendStatus( int status, String message) throws IOException {
- ///*DEBUG*/ try {throw new Exception(); } catch(Exception ex) {ex.printStackTrace();}
- statusSB.setLength(0);
- statusSB.append("Status: " ).append( status ).append(" ").append(message).append("\r\n");
- sout.write(statusSB.toString().getBytes());
- statusSB.setLength(0);
+ printHead("Status: " );
+ printHead( String.valueOf( status ));
+ printHead( " " );
+ printHead( message );
+ printHead("\r\n");
}
}
1.9 +60 -34 jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpResponseAdapter.java
Index: HttpResponseAdapter.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpResponseAdapter.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- HttpResponseAdapter.java 2000/04/25 17:54:26 1.8
+++ HttpResponseAdapter.java 2000/05/23 20:58:25 1.9
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpResponseAdapter.java,v 1.8 2000/04/25 17:54:26 costin Exp $
- * $Revision: 1.8 $
- * $Date: 2000/04/25 17:54:26 $
+ * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpResponseAdapter.java,v 1.9 2000/05/23 20:58:25 costin Exp $
+ * $Revision: 1.9 $
+ * $Date: 2000/05/23 20:58:25 $
*
* ====================================================================
*
@@ -82,21 +82,17 @@
public class HttpResponseAdapter extends ResponseImpl {
protected OutputStream sout;
- // no need to create new objects/request,
- // avoid extra String creation
- protected StringBuffer statusSB;
- protected StringBuffer headersSB;
-
+ protected static final int DEFAULT_HEAD_BUFFER_SIZE = 1024;
+ protected byte[] buffer = new byte[DEFAULT_HEAD_BUFFER_SIZE];
+ protected int bufferCount = 0;
+
public HttpResponseAdapter() {
super();
- statusSB=new StringBuffer();
- headersSB=new StringBuffer();
}
public void recycle() {
super.recycle();
- statusSB.setLength(0);
- headersSB.setLength(0);
+ bufferCount=0;
}
public void setOutputStream(OutputStream os) {
@@ -110,23 +106,21 @@
sendStatus( status, ResponseImpl.getMessage( status ));
- Enumeration e = headers.names();
- while (e.hasMoreElements()) {
- String name = (String)e.nextElement();
- String values[] = headers.getHeaders(name);
- for( int i=0; i< values.length; i++ ) {
- String value=values[i];
- headersSB.setLength(0);
- headersSB.append(name).append(": ").append(value).append("\r\n");
- // try {
- sout.write( headersSB.toString().getBytes(Constants.CharacterEncoding.Default) );
- // } catch( IOException ex ) {
- // ex.printStackTrace();
- //XXX mark the error - should abandon everything
- //}
- }
+ int count=headers.size();
+ for( int i=0; i<count; i++ ) {
+ MimeHeaderField field=headers.getField( i );
+ // response headers are set by the servlet, so probably we have only
+ // Strings.
+ // XXX date, cookies, etc shoud be extracted from response
+ printHead( field.getName() );
+ printHead(": ");
+ printHead( field.getValue() );
+ printHead("\r\n");
}
- sout.write( CRLF, 0, 2 );
+
+ printHead( "\r\n" );
+
+ sout.write( buffer, 0, bufferCount );
sout.flush();
}
@@ -134,15 +128,47 @@
HTTP response is the status line
*/
protected void sendStatus( int status, String message ) throws IOException {
- // statusSB.reset();
- statusSB.append("HTTP/1.0 ").append(status);
- if(message!=null) statusSB.append(" ").append(message);
- statusSB.append("\r\n");
- sout.write(statusSB.toString().getBytes(Constants.CharacterEncoding.Default));
- statusSB.setLength(0);
+ printHead("HTTP/1.0 ");
+ printHead(String.valueOf(status));
+ if(message!=null) {
+ printHead(" ");
+ printHead(message);
+ }
+ printHead("\r\n");
}
public void doWrite( byte buffer[], int pos, int count) throws IOException {
sout.write( buffer, pos, count);
}
+
+ // From BufferedServletOutputStream
+ // XXX will be moved in a new in/out system, temp. code
+ // Right now it's not worse than BOS
+ protected void printHead( String s ) {
+ if (s==null) s="null";
+
+ int len = s.length();
+ for (int i = 0; i < len; i++) {
+ char c = s.charAt (i);
+
+ //
+ // XXX NOTE: This is clearly incorrect for many strings,
+ // but is the only consistent approach within the current
+ // servlet framework. It must suffice until servlet output
+ // streams properly encode their output.
+ //
+ if ((c & 0xff00) != 0) { // high order byte must be zero
+ // XXX will go away after we change the I/O system
+ System.out.println("Header character is not iso8859_1, not supported yet: " + c ) ;
+ }
+ if( bufferCount >= buffer.length ) {
+ byte bufferNew[]=new byte[ buffer.length * 2 ];
+ System.arraycopy( buffer,0, bufferNew, 0, buffer.length );
+ buffer=bufferNew;
+ }
+ buffer[bufferCount] = (byte)c;
+ bufferCount++;
+ }
+ }
+
}
1.2 +3 -4 jakarta-tomcat/src/share/org/apache/tomcat/util/MessageString.java
Index: MessageString.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/MessageString.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- MessageString.java 1999/10/09 00:20:56 1.1
+++ MessageString.java 2000/05/23 20:58:26 1.2
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/MessageString.java,v 1.1 1999/10/09 00:20:56 duncan Exp $
- * $Revision: 1.1 $
- * $Date: 1999/10/09 00:20:56 $
+ * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/MessageString.java,v 1.2 2000/05/23 20:58:26 costin Exp $
+ * $Revision: 1.2 $
+ * $Date: 2000/05/23 20:58:26 $
*
* ====================================================================
*
@@ -75,7 +75,6 @@
*
* @author dac@eng.sun.com
*/
-
public class MessageString extends MessageBytes {
/**
* The message String.
1.5 +14 -34 jakarta-tomcat/src/share/org/apache/tomcat/util/MimeHeaderField.java
Index: MimeHeaderField.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/MimeHeaderField.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- MimeHeaderField.java 2000/05/02 19:58:41 1.4
+++ MimeHeaderField.java 2000/05/23 20:58:27 1.5
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/MimeHeaderField.java,v 1.4 2000/05/02 19:58:41 costin Exp $
- * $Revision: 1.4 $
- * $Date: 2000/05/02 19:58:41 $
+ * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/MimeHeaderField.java,v 1.5 2000/05/23 20:58:27 costin Exp $
+ * $Revision: 1.5 $
+ * $Date: 2000/05/23 20:58:27 $
*
* ====================================================================
*
@@ -70,11 +70,18 @@
/**
* This class is used to represent a MIME header field.
+ * It uses MessageString, and can be used in 0-GC mode ( no
+ * garbage generated unless toString() is called )
*
+ *
* @author dac@eng.sun.com
* @author James Todd [gonzo@eng.sun.com]
*/
public class MimeHeaderField {
+ public static final byte[] charval = {
+ (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4',
+ (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9'
+ };
private StringManager sm =
StringManager.getManager("org.apache.tomcat.util");
@@ -82,31 +89,26 @@
/**
* The header field name.
*/
-
protected final MessageString name = new MessageString();
/**
* The header field value.
*/
-
protected final MessageString value = new MessageString();
/**
* The header field integer value.
*/
-
protected int intValue;
/**
* The header field Date value.
*/
-
protected final HttpDate dateValue = new HttpDate(0);
/**
* The header field value type.
*/
-
protected int type = T_NULL;
protected static final int T_NULL = 0;
@@ -114,22 +116,15 @@
protected static final int T_INT = 2;
protected static final int T_DATE = 3;
- private static final byte[] charval = {
- (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4',
- (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9'
- };
-
/**
* Creates a new, uninitialized header field.
*/
-
public MimeHeaderField() {
}
/**
* Resets the header field to an uninitialized state.
*/
-
public void reset() {
name.reset();
value.reset();
@@ -140,7 +135,6 @@
* Sets the header field name to the specified string.
* @param s the header field name String
*/
-
public void setName(String s) {
name.setString(s);
}
@@ -151,7 +145,6 @@
* @param off the start offset of the bytes
* @param len the length of the bytes
*/
-
public void setName(byte[] b, int off, int len) {
name.setBytes(b, off, len);
}
@@ -160,7 +153,6 @@
* Sets the header field value to the specified string.
* @param s the header field value String
*/
-
public void setValue(String s) {
value.setString(s);
type = T_STR;
@@ -172,7 +164,6 @@
* @param off the start offset of the bytes
* @param len the length of the bytes
*/
-
public void setValue(byte[] b, int off, int len) {
value.setBytes(b, off, len);
type = T_STR;
@@ -182,7 +173,6 @@
* Sets the header field to the specified integer value.
* @param i the header field integer value
*/
-
public void setIntValue(int i) {
intValue = i;
type = T_INT;
@@ -192,7 +182,6 @@
* Sets the header field date value to the specified time.
* @param t the time in milliseconds since the epoch
*/
-
public void setDateValue(long t) {
dateValue.setTime(t);
type = T_DATE;
@@ -201,7 +190,6 @@
/**
* Sets the header field date value to the current time.
*/
-
public void setDateValue() {
dateValue.setTime();
type = T_DATE;
@@ -210,7 +198,6 @@
/**
* Returns the header field name as a String.
*/
-
public String getName() {
return name.toString();
}
@@ -218,7 +205,6 @@
/**
* Returns the header field value as a String, or null if not set.
*/
-
public String getValue() {
switch (type) {
case T_STR:
@@ -238,7 +224,8 @@
*/
public int getIntValue()
- throws NumberFormatException {
+ throws NumberFormatException
+ {
switch (type) {
case T_INT:
return intValue;
@@ -256,9 +243,9 @@
* @return the header date value in number of milliseconds since the epoch
* @exception IllegalArgumentException if the date format was invalid
*/
-
public long getDateValue()
- throws IllegalArgumentException {
+ throws IllegalArgumentException
+ {
switch (type) {
case T_DATE:
return dateValue.getTime();
@@ -276,7 +263,6 @@
* @param target - the integer to convert. Must be in the range [0..2^31].
* @return the number of bytes added to buf
*/
-
private int intGetBytes(int target, byte buf[], int offset) {
int power = 1000000000; // magnitude of highest digit we can handle
int this_digit;
@@ -309,7 +295,6 @@
* Put the bytes for this header into buf starting at offset buf_offset.
* @return the length of what was added
*/
-
public int getBytes(byte buf[], int buf_offset) {
int len;
int start_pt = buf_offset;
@@ -356,7 +341,6 @@
* @param len the length of the bytes
* @exception IllegalArgumentException if the header format was invalid
*/
-
public boolean parse(byte[] b, int off, int len)
{
int start = off;
@@ -389,7 +373,6 @@
/**
* Writes this header field to the specified servlet output stream.
*/
-
public void write(ServletOutputStream out)
throws IOException {
name.write(out);
@@ -417,7 +400,6 @@
* case is ignored in the comparison.
* @param s the string to compare
*/
-
public boolean nameEquals(String s) {
return name.equalsIgnoreCase(s);
}
@@ -429,7 +411,6 @@
* @param off the start offset of the bytes
* @param len the length of the bytes
*/
-
public boolean nameEquals(byte[] b, int off, int len) {
return name.equalsIgnoreCase(b, off, len);
}
@@ -437,7 +418,6 @@
/**
* Returns a string representation of the header field.
*/
-
public String toString() {
StringBuffer sb = new StringBuffer();
1.6 +164 -163 jakarta-tomcat/src/share/org/apache/tomcat/util/MimeHeaders.java
Index: MimeHeaders.java
===================================================================
RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/MimeHeaders.java,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- MimeHeaders.java 2000/05/23 16:57:08 1.5
+++ MimeHeaders.java 2000/05/23 20:58:27 1.6
@@ -1,7 +1,7 @@
/*
- * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/MimeHeaders.java,v 1.5 2000/05/23 16:57:08 costin Exp $
- * $Revision: 1.5 $
- * $Date: 2000/05/23 16:57:08 $
+ * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/MimeHeaders.java,v 1.6 2000/05/23 20:58:27 costin Exp $
+ * $Revision: 1.6 $
+ * $Date: 2000/05/23 20:58:27 $
*
* ====================================================================
*
@@ -96,48 +96,51 @@
* only available as strings. They may be accessed by index (treating
* the header as an array of fields), or by name (returning an array
* of string values).
+ */
+
+/**
+ * Memory-efficient repository for Mime Headers. When the object is recycled, it
+ * will keep the allocated headers[] and all the MimeHeaderField - no GC is generated.
*
+ * For input headers it is possible to use the MessageByte for Fileds - so no GC
+ * will be generated.
+ *
+ * The only garbage is generated when using the String for header names/values -
+ * this can't be avoided when the servlet calls header methods, but is easy
+ * to avoid inside tomcat. The goal is to use _only_ MessageByte-based Fields,
+ * and reduce to 0 the memory overhead of tomcat.
+ *
+ * TODO:
+ * XXX one-buffer parsing - for http ( other protocols don't need that )
+ * XXX remove unused methods
+ * XXX External enumerations, with 0 GC.
+ * XXX use HeaderName ID
+ *
+ *
* @author dac@eng.sun.com
* @author James Todd [gonzo@eng.sun.com]
+ * @author Costin Manolache
*/
-
public class MimeHeaders {
-
- private StringManager sm =
- StringManager.getManager("org.apache.tomcat.util");
-
+ /** Initial size - should be == average number of headers per request
+ * XXX make it configurable ( fine-tuning of web-apps )
+ */
+ public static final int DEFAULT_HEADER_SIZE=8;
+
/**
* The header fields.
*/
-
- private MimeHeaderField[] headers = new MimeHeaderField[8];
+ private MimeHeaderField[] headers = new MimeHeaderField[DEFAULT_HEADER_SIZE];
/**
* The current number of header fields.
*/
-
private int count;
/**
- * A buffer used when parsing headers.
- */
-
- private byte[] buf;
-
- /**
- * Creates a new MimeHeaders object using the specified buffer size.
- * @param len the buffer size initially used for parsing headers
- */
-
- public MimeHeaders(int len) {
- buf = new byte[len];
- }
-
- /**
* Creates a new MimeHeaders object using a default buffer size.
*/
public MimeHeaders() {
- this(512);
}
/**
@@ -153,17 +156,83 @@
/**
* Returns the current number of header fields.
*/
-
public int size() {
return count;
}
/**
+ * Returns the Nth header field, or null if there is no such header.
+ * This may be used to iterate through all header fields.
+ */
+ public MimeHeaderField getField(int n) {
+ return n >= 0 && n < count ? headers[n] : null;
+ }
+
+
+ /**
+ * Finds and returns a header field with the given name. If no such
+ * field exists, null is returned. If more than one such field is
+ * in the header, an arbitrary one is returned.
+ */
+ public MimeHeaderField find(String name) {
+ for (int i = 0; i < count; i++) {
+ if (headers[i].nameEquals(name)) {
+ return headers[i];
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Adds a partially constructed field to the header. This
+ * field has not had its name or value initialized.
+ */
+ public MimeHeaderField putHeader() {
+ MimeHeaderField mh;
+ int len = headers.length;
+ if (count >= len) {
+ // expand header list array
+ MimeHeaderField tmp[] = new MimeHeaderField[count * 2];
+ System.arraycopy(headers, 0, tmp, 0, len);
+ headers = tmp;
+ }
+ if ((mh = headers[count]) == null) {
+ headers[count] = mh = new MimeHeaderField();
+ }
+ count++;
+ return mh;
+ }
+
+
+
+
+ // --------------------
+ // Please avoid using any of the methods following this line.
+ // ( most of them will generate GC, or are http sepecific )
+ // ------------------------------------------------------------
+ private StringManager sm =
+ StringManager.getManager("org.apache.tomcat.util");
+ int bufSize=512; // default
+ /**
+ * A buffer used when parsing headers.
+ */
+ private byte[] buf=null;
+
+
+ /**
+ * Creates a new MimeHeaders object using the specified buffer size.
+ * @param len the buffer size initially used for parsing headers
+ */
+ public MimeHeaders(int len) {
+ bufSize=len;
+ // buf = new byte[len];
+ }
+
+ /**
* Returns an enumeration of strings representing the header field names.
* Field names may appear multiple times in this enumeration, indicating
* that multiple fields with that name exist in this header.
*/
-
public Enumeration names() {
return new MimeHeadersEnumerator(this);
}
@@ -177,7 +246,6 @@
* @param name the header name
* @param s the header field string value
*/
-
public void putHeader(String name, String s) {
putHeader(name).setValue(s);
}
@@ -191,7 +259,6 @@
* @param name the header name
* @param i the header field integer value
*/
-
public void putIntHeader(String name, int i) {
putHeader(name).setIntValue(i);
}
@@ -206,7 +273,6 @@
* @param name the header name
* @param t the time in number of milliseconds since the epoch
*/
-
public void putDateHeader(String name, long t) {
putHeader(name).setDateValue(t);
}
@@ -219,7 +285,6 @@
* Creates a new header field whose value is the current date and time.
* @param name the header name
*/
-
public void putDateHeader(String name) {
putHeader(name).setDateValue();
}
@@ -235,7 +300,6 @@
* @param name the header field name
* @return the string value of the field, or null if none found
*/
-
public String getHeader(String name) {
MimeHeaderField mh = find(name);
@@ -249,7 +313,6 @@
* @param name the header field name
* @return array values of the fields, or null if none found
*/
-
public String[] getHeaders(String name) {
Vector values = getHeadersVector(name);
@@ -297,7 +360,6 @@
* since the epoch, or -1 if the header was not found
* @exception IllegalArgumentException if the date format was invalid
*/
-
public long getDateHeader(String name) throws IllegalArgumentException {
MimeHeaderField mh = find(name);
@@ -309,7 +371,6 @@
* if there were fewer than (n + 1) fields. This can be used to iterate
* through all the fields in the header.
*/
-
public String getHeaderName(int n) {
return n >= 0 && n < count ? headers[n].getName() : null;
}
@@ -319,24 +380,13 @@
* if there were fewer than (n + 1) fields. This can be used along
* with getHeaderName to iterate through all the fields in the header.
*/
-
public String getHeader(int n) {
return n >= 0 && n < count ? headers[n].getValue() : null;
}
/**
- * Returns the Nth header field, or null if there is no such header.
- * This may be used to iterate through all header fields.
- */
-
- public MimeHeaderField getField(int n) {
- return n >= 0 && n < count ? headers[n] : null;
- }
-
- /**
* Returns the number of fields using a given field name.
*/
-
public int getFieldCount (String name) {
int retval = 0;
@@ -348,27 +398,10 @@
}
/**
- * Finds and returns a header field with the given name. If no such
- * field exists, null is returned. If more than one such field is
- * in the header, an arbitrary one is returned.
- */
-
- protected MimeHeaderField find(String name) {
- for (int i = 0; i < count; i++) {
- if (headers[i].nameEquals(name)) {
- return headers[i];
- }
- }
-
- return null;
- }
-
- /**
* Removes a header field with the specified name. Does nothing
* if such a field could not be found.
* @param name the name of the header field to be removed
*/
-
public void removeHeader(String name) {
// XXX
// warning: rather sticky code; heavily tuned
@@ -393,24 +426,87 @@
* otherwise returns false.
* @param name the field name
*/
-
public boolean containsHeader(String name) {
return find(name) != null;
}
/**
+ * Writes out header fields to the specified servlet output stream.
+ * @param out the servlet output stream
+ * @exception IOException if an I/O error has occurred
+ */
+ public void write(ServletOutputStream out) throws IOException {
+ for (int i = 0; i < count; i++) {
+ headers[i].write(out);
+ }
+
+ out.println();
+ }
+
+ /**
+ * Finds a header field given name. If the header doesn't exist,
+ * it will create a new one.
+ * @param name the header field name
+ * @return the new field
+ */
+ protected MimeHeaderField putHeader(String name) {
+ if (containsHeader(name)) {
+ removeHeader(name);
+ }
+
+ return addHeader(name);
+ }
+
+ protected MimeHeaderField addHeader(String name) {
+ MimeHeaderField mh = putHeader();
+
+ mh.setName(name);
+
+ return mh;
+ }
+
+ /**
+ * Creates a new header with given name, and add it to the headers.
+ * @param name the header field name
+ * @param s the header value
+ * @return the new field
+ */
+ public void appendHeader(String name, String s) {
+ MimeHeaderField mh = putHeader();
+
+ mh.setName(name);
+ mh.setValue(s);
+ }
+
+ /**
+ * Get the current header fields in the byte array buf. The headers
+ * fields are placed starting at offset buf_offset.
+ * @return the number of bytes written into buf.
+ */
+ public int getAll(byte buf[], int buf_offset) {
+ int start_pt = buf_offset;
+
+ for (int i = 0; i < count; i++) {
+ buf_offset += headers[i].getBytes(buf, buf_offset);
+ }
+
+ return buf_offset - start_pt;
+ }
+
+
+ /**
* Reads header fields from the specified servlet input stream until
* a blank line is encountered.
* @param in the servlet input stream
* @exception IllegalArgumentException if the header format was invalid
* @exception IOException if an I/O error has occurred
*/
-
public void read(ServletInputStream in) throws IOException {
// use pre-allocated buffer if possible
byte[] b;
if (count == 0) {
+ if( buf==null ) buf=new byte[bufSize];
b = buf;
} else {
b = new byte[buf.length];
@@ -459,113 +555,17 @@
// XXX this does not currently handle headers which
// are folded to take more than one line.
-
MimeHeaderField mhf=putHeader();
if( ! mhf.parse(b, start, off - start) ) {
// error parsing header
return;
}
-
}
}
/**
- * Writes out header fields to the specified servlet output stream.
- * @param out the servlet output stream
- * @exception IOException if an I/O error has occurred
- */
-
- public void write(ServletOutputStream out) throws IOException {
- for (int i = 0; i < count; i++) {
- headers[i].write(out);
- }
-
- out.println();
- }
-
- /**
- * Finds a header field given name. If the header doesn't exist,
- * it will create a new one.
- * @param name the header field name
- * @return the new field
- */
-
- protected MimeHeaderField putHeader(String name) {
- if (containsHeader(name)) {
- removeHeader(name);
- }
-
- return addHeader(name);
- }
-
- protected MimeHeaderField addHeader(String name) {
- MimeHeaderField mh = putHeader();
-
- mh.setName(name);
-
- return mh;
- }
-
- /**
- * Creates a new header with given name, and add it to the headers.
- * @param name the header field name
- * @param s the header value
- * @return the new field
- */
-
- public void appendHeader(String name, String s) {
- MimeHeaderField mh = putHeader();
-
- mh.setName(name);
- mh.setValue(s);
- }
-
- /**
- * Adds a partially constructed field to the header. This
- * field has not had its name or value initialized.
- */
-
- protected MimeHeaderField putHeader() {
- MimeHeaderField mh;
- int len = headers.length;
-
- if (count >= len) {
- // expand header list array
- MimeHeaderField tmp[] = new MimeHeaderField[count * 2];
-
- System.arraycopy(headers, 0, tmp, 0, len);
- headers = tmp;
- }
-
- if ((mh = headers[count]) == null) {
- headers[count] = mh = new MimeHeaderField();
- }
-
- count++;
-
- return mh;
- }
-
- /**
- * Get the current header fields in the byte array buf. The headers
- * fields are placed starting at offset buf_offset.
- * @return the number of bytes written into buf.
- */
-
- public int getAll(byte buf[], int buf_offset) {
- int start_pt = buf_offset;
-
- for (int i = 0; i < count; i++) {
- buf_offset += headers[i].getBytes(buf, buf_offset);
- }
-
- return buf_offset - start_pt;
- }
-
- /**
* Returns a lengthly string representation of the current header fields.
*/
-
public String toString() {
StringBuffer sb = new StringBuffer();
@@ -628,3 +628,4 @@
}
}
}
+