diff --git a/autotest/AutoTestContentHandler.java b/autotest/AutoTestContentHandler.java index e97efbd4d..06981e4b1 100644 --- a/autotest/AutoTestContentHandler.java +++ b/autotest/AutoTestContentHandler.java @@ -5,11 +5,6 @@ // (c) COPYRIGHT MIT, ERCIM and Keio, 2003. // Please first read the full copyright statement in file COPYRIGHT.html -import org.w3c.www.http.HTTP; -import org.w3c.www.protocol.http.HttpException; -import org.w3c.www.protocol.http.HttpManager; -import org.w3c.www.protocol.http.Reply; -import org.w3c.www.protocol.http.Request; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.Locator; @@ -20,6 +15,7 @@ import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; +import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; @@ -293,14 +289,10 @@ public void endElement(String nameSpaceURI, String localName, String rawName) val += PARAMS; try { - HttpManager manager = HttpManager.getManager(); - Request request = manager.createRequest(); - request.setMethod(HTTP.GET); + HttpURLConnection conn = (HttpURLConnection) new URL(val).openConnection(); System.err.println(val); - request.setURL(new URL(val)); - Reply reply = manager.runRequest(request); // Get the reply input stream that contains the actual data: - InputStream res = reply.getInputStream(); + InputStream res = conn.getInputStream(); int currentChar; StringBuffer buf = new StringBuffer(); @@ -308,7 +300,7 @@ public void endElement(String nameSpaceURI, String localName, String rawName) buf.append((char) currentChar); } - if (reply.getStatus() == 500) { // Internal Server Error + if (conn.getResponseCode() == 500) { // Internal Server Error if (buf.indexOf("env:Sender") != -1) { printError(val, "Reply status code: 500
" + "Invalid URL: Sender error"); @@ -348,8 +340,6 @@ public void endElement(String nameSpaceURI, String localName, String rawName) printError(val, e.getMessage()); } catch (IOException e) { printError(val, e.getMessage()); - } catch (HttpException e) { - printError(val, e.getMessage()); } isFile = false; diff --git a/build.xml b/build.xml index 417780e63..db659e1eb 100644 --- a/build.xml +++ b/build.xml @@ -31,7 +31,6 @@ - @@ -57,7 +56,6 @@ - @@ -77,7 +75,6 @@ - diff --git a/org/w3c/css/util/ApplContext.java b/org/w3c/css/util/ApplContext.java index f6f919bcb..405fb8ffc 100644 --- a/org/w3c/css/util/ApplContext.java +++ b/org/w3c/css/util/ApplContext.java @@ -13,7 +13,6 @@ import org.w3c.css.parser.Frame; import org.w3c.www.http.HttpAcceptCharset; import org.w3c.www.http.HttpAcceptCharsetList; -import org.w3c.www.http.HttpFactory; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -367,10 +366,10 @@ public void setContentEncoding(String acceptCharset) { // uses some Jigsaw classes to parse the Accept-Charset // these classes need to load a lot of stuff, so it may be quite // long the first time - HttpAcceptCharsetList charsetList; - HttpAcceptCharset[] charsets; + HttpAcceptCharsetList charsetList = new HttpAcceptCharsetList(); + charsetList.setString(acceptCharset); - charsetList = HttpFactory.parseAcceptCharsetList(acceptCharset); + HttpAcceptCharset[] charsets; charsets = (HttpAcceptCharset[]) charsetList.getValue(); String encoding = null; diff --git a/org/w3c/tools/resources/ProtocolException.java b/org/w3c/tools/resources/ProtocolException.java new file mode 100644 index 000000000..6a80f521f --- /dev/null +++ b/org/w3c/tools/resources/ProtocolException.java @@ -0,0 +1,14 @@ +// ProtocolException.java +// $Id: ProtocolException.java,v 1.2 2000/08/16 21:37:53 ylafon Exp $ +// (c) COPYRIGHT MIT and INRIA, 1996. +// Please first read the full copyright statement in file COPYRIGHT.html + +package org.w3c.tools.resources ; + +public class ProtocolException extends Exception { + + public ProtocolException (String msg) { + super (msg) ; + } + +} diff --git a/org/w3c/www/http/HeaderValue.java b/org/w3c/www/http/HeaderValue.java new file mode 100644 index 000000000..bd7fce115 --- /dev/null +++ b/org/w3c/www/http/HeaderValue.java @@ -0,0 +1,164 @@ +// HeaderValue.java +// $Id$ +// (c) COPYRIGHT MIT and INRIA, 1996. +// Please first read the full copyright statement in file COPYRIGHT.html + +package org.w3c.www.http; + +public abstract class HeaderValue implements Cloneable { + /** + * The header value, as a byte array, if available. + */ + protected byte raw[] = null; + /** + * The offset of the value in the above buffer, in case the buffer is + * shared. + */ + protected int roff = -1; + /** + * The length of the byte value in case the above buffer is shared. + */ + protected int rlen = -1; + /** + * Are the parsed values up to date with the lastly set unparsed value ? + */ + protected boolean isValid = false; + + /** + * Parse this header value into its various components. + * @exception HttpParserException if unable to parse. + */ + + abstract protected void parse() + throws HttpParserException; + + /** + * Update the RFC822 compatible header value for this object. + */ + + abstract protected void updateByteValue(); + + /** + * Compute the new RFC822 compatible representation of this header value. + * If our value is up to date, we just return, otherwise, the abstract + * updateByteValue is called to perform the job. + */ + + protected final void checkByteValue() { + if ( raw == null ) { + updateByteValue(); + roff = 0; + rlen = raw.length; + } + } + + /** + * Validate the parsed value according to the last set raw value. + * This will trigger the header value parsing, if it is required at this + * point. + * @exception HttpInvalidValueException If the value couldn't be parsed + * properly. + */ + + protected final void validate() + throws HttpInvalidValueException + { + if ( isValid ) + return; + try { + parse(); + } catch (HttpParserException ex) { + throw new HttpInvalidValueException(ex.getMessage()); + } + isValid = true; + } + + /** + * Invalidate the current byte value for this header, if any. + */ + + protected void invalidateByteValue() { + raw = null; + } + + /** + * Emit a parsing error. + * @param msg The error message. + * @exception HttpParserException If the parsing failed. + */ + + protected void error(String msg) + throws HttpParserException + { + throw new HttpParserException(msg); + } + + /** + * Append this header byte value to the given buffer. + * @param buf The buffer to append the byte value to. + */ + + public void appendValue(HttpBuffer buf) { + checkByteValue(); + buf.append(raw, roff, rlen); + } + + /** + * Return the HTTP encoding for this header value. + * This method is slow, and defeats nearly all the over-engeneered + * optimization of the HTTP parser. + * @return A String representing the header value in a format compatible + * with HTTP. + */ + + public String toExternalForm() { + checkByteValue(); + return new String(raw, 0, roff, rlen-roff); + } + + /** + * Print this header value as it would be emitted. + * @return A String representation of this header value. + */ + + public String toString() { + return toExternalForm(); + } + + /** + * Set this Header Value by parsing the given String. + * @param strval The String value for that object. + * @return Itself. + */ + + public void setString(String strval) { + int slen = strval.length(); + raw = new byte[slen]; + roff = 0; + rlen = slen; + strval.getBytes(0, slen, raw, 0); + isValid = false; + } + + /** + * Get this header parsed value, in its native type. + * HeaderValue implementors can be used as wrappers for the actual + * parsed header value. In such case this method should return the wrapped + * value (you would otherwise, probably want to return + * this). + */ + + abstract public Object getValue() ; + + // needs to define it as this is an abstract class + protected Object clone() + throws CloneNotSupportedException + { + return super.clone(); + } + + public HeaderValue() { + isValid = false; + } + +} diff --git a/org/w3c/www/http/HttpAcceptCharset.java b/org/w3c/www/http/HttpAcceptCharset.java new file mode 100644 index 000000000..ae901c4d8 --- /dev/null +++ b/org/w3c/www/http/HttpAcceptCharset.java @@ -0,0 +1,111 @@ +// HttpAcceptCharset.java +// $Id$ +// (c) COPYRIGHT MIT and INRIA, 1996. +// Please first read the full copyright statement in file COPYRIGHT.html + +package org.w3c.www.http; + +public class HttpAcceptCharset extends HeaderValue { + String charset = null; + double quality = 1.0; + HttpAcceptCharsetList list = null; + + /** + * parse. + * @exception HttpParserException if parsing failed. + */ + protected void parse() + throws HttpParserException + { + ParseState ps = new ParseState(roff, rlen); + ps.separator = (byte) ';'; + ps.spaceIsSep = false; + // Get the charset: + if ( HttpParser.nextItem(raw, ps) < 0 ) + error("Invalid Accept-Charset: no charset."); + this.charset = new String(raw, 0, ps.start, ps.end-ps.start); + // And the optional quality: + ps.prepare(); + ps.separator = (byte) '='; + if ( HttpParser.nextItem(raw, ps) < 0 ) { + this.quality = 1.0; + } else { + ps.prepare(); + this.quality = HttpParser.parseQuality(raw, ps); + } + } + + protected void invalidateByteValue() { + super.invalidateByteValue(); + if ( list != null ) + list.invalidateByteValue(); + } + + protected void updateByteValue() { + HttpBuffer buf = new HttpBuffer(); + buf.append(charset); + buf.append(';'); + buf.append(quality); + raw = buf.getByteCopy(); + roff = 0; + rlen = raw.length; + } + + public Object getValue() { + validate(); + return this; + } + + /** + * Get this accept charset clause charset. + * @return A String encoding the charset token. + */ + + public String getCharset() { + validate(); + return charset; + } + + /** + * Set the charset accepted by this clause. + * @param charset The accepted charset. + */ + + public void setCharset(String charset) { + if ( this.charset.equals(charset) ) + return; + invalidateByteValue(); + this.charset = charset; + } + + /** + * Get the quality at which this charset is accepted. + * @return A double value, encoding the quality, or 1.0 + * if undefined. + */ + + public double getQuality() { + validate(); + return quality; + } + + /** + * Set the quality under which this charset is accepted. + * @param quality The quality for this charset. + */ + + public void setQuality(double quality) { + if ( this.quality != quality ) + invalidateByteValue(); + this.quality = quality; + } + + HttpAcceptCharset(HttpAcceptCharsetList list, byte raw[], int o, int l) { + this.list = list; + this.raw = raw; + this.roff = o; + this.rlen = l; + this.isValid = false; + } + +} diff --git a/org/w3c/www/http/HttpAcceptCharsetList.java b/org/w3c/www/http/HttpAcceptCharsetList.java new file mode 100644 index 000000000..d3ae5a8b1 --- /dev/null +++ b/org/w3c/www/http/HttpAcceptCharsetList.java @@ -0,0 +1,53 @@ +// HttpAcceptCharsetList.java +// $Id$ +// (c) COPYRIGHT MIT and INRIA, 1996. +// Please first read the full copyright statement in file COPYRIGHT.html + +package org.w3c.www.http; + +import java.util.Vector; + +public class HttpAcceptCharsetList extends HeaderValue { + HttpAcceptCharset charsets[] = null; + + protected void parse() { + Vector vl = new Vector(4); + ParseState ps = new ParseState(roff, rlen); + ps.separator = (byte) ','; + ps.spaceIsSep = false; + while ( HttpParser.nextItem(raw, ps) >= 0 ) { + vl.addElement(new HttpAcceptCharset(this, raw, ps.start, ps.end)); + ps.prepare(); + } + charsets = new HttpAcceptCharset[vl.size()]; + vl.copyInto(charsets); + } + + protected void updateByteValue() { + HttpBuffer buf = new HttpBuffer(); + if ( charsets != null ) { + for (int i = 0 ; i < charsets.length ; i++) { + if ( i > 0 ) + buf.append(','); + charsets[i].appendValue(buf); + } + raw = buf.getByteCopy(); + roff = 0; + rlen = raw.length; + } else { + raw = new byte[0]; + roff = 0; + rlen = 0; + } + } + + public Object getValue() { + validate(); + return charsets; + } + + public HttpAcceptCharsetList() { + this.isValid = false; + } + +} diff --git a/org/w3c/www/http/HttpBuffer.java b/org/w3c/www/http/HttpBuffer.java new file mode 100644 index 000000000..8c0a32fc4 --- /dev/null +++ b/org/w3c/www/http/HttpBuffer.java @@ -0,0 +1,87 @@ +// HttpBuffer.java +// $Id$ +// (c) COPYRIGHT MIT and INRIA, 1996. +// Please first read the full copyright statement in file COPYRIGHT.html + +package org.w3c.www.http; + +/** + * A cool StringBuffer like class, for converting header values to String. + * Note that for good reasons, this class is not public. + */ + +class HttpBuffer { + private static final int INIT_SIZE = 128 ; + + byte buf[]; + int len = 0; + + final void append(byte b) { + ensureCapacity(1); + buf[len++] = b; + } + + final void append(char ch) { + append((byte) ch); + } + + final void ensureCapacity(int sz) { + int req = len + sz ; + if ( req >= buf.length ) { + int nsz = buf.length << 1; + if ( nsz < req ) + nsz = req + 1; + byte nb[] = new byte[nsz]; + System.arraycopy(buf, 0, nb, 0, len); + buf = nb; + } + } + + void append(byte b[], int o, int l) { + ensureCapacity(l); + System.arraycopy(b, o, buf, len, l); + len += l; + } + + void append(String str) { + int l = str.length(); + ensureCapacity(l); + str.getBytes(0, l, buf, len); + len += l; + } + + void append(double d) { + append(Double.toString(d)); + } + + public String toString() { + return new String(buf, 0, 0, len); + } + + /** + * Get a copy of the current byte buffer. + */ + + public byte[] getByteCopy() { + byte v[] = new byte[len]; + System.arraycopy(buf, 0, v, 0, len); + return v; + } + + public final byte[] getBytes() { + return buf; + } + + public final int length() { + return len; + } + + public final void reset() { + len = 0; + } + + HttpBuffer() { + this.buf = new byte[INIT_SIZE]; + } + +} diff --git a/org/w3c/www/http/HttpInvalidValueException.java b/org/w3c/www/http/HttpInvalidValueException.java new file mode 100644 index 000000000..222cf98b1 --- /dev/null +++ b/org/w3c/www/http/HttpInvalidValueException.java @@ -0,0 +1,14 @@ +// HttpInvalidValueException.java +// $Id$ +// (c) COPYRIGHT MIT and INRIA, 1996. +// Please first read the full copyright statement in file COPYRIGHT.html + +package org.w3c.www.http; + +public class HttpInvalidValueException extends RuntimeException { + + public HttpInvalidValueException(String msg) { + super(msg); + } + +} diff --git a/org/w3c/www/http/HttpParser.java b/org/w3c/www/http/HttpParser.java new file mode 100644 index 000000000..4a8af7fa6 --- /dev/null +++ b/org/w3c/www/http/HttpParser.java @@ -0,0 +1,141 @@ +// HttpParser.java +// $Id$ +// (c) COPYRIGHT MIT and INRIA, 1996. +// Please first read the full copyright statement in file COPYRIGHT.html + +package org.w3c.www.http; + +/** + * A private class to help with the parsing. + * Contains only some static method, helping to parse various byte + * buffers into Java object (Yes, I am still and again trying to reduce + * memory consumption). + *

I don't know wether this sucks or not. One hand I am sparing a tremedous + * amount of Strings creation, on the other end I am recoding a number of + * parsers that are available on String instances. + */ + +public class HttpParser { + private static final boolean debug = false; + + /** + * Emit an error. + * @param mth The method trigerring the error. + * @param msg An associated message. + * @exception HttpInvalidValueException To indicate the error to caller. + */ + + protected static void error(String mth, String msg) + throws HttpInvalidValueException + { + throw new HttpInvalidValueException(mth+": "+msg); + } + + /** + * Skip leading LWS, not including CR LF. + * Update the input offset, after any leading space. + * @param buf The buffer to be parsed. + * @param ptr The buffer pointer to be updated on return. + * @return The potentially advanced buffer input offset. + */ + + public static final int skipSpaces(byte buf[], ParseState ps) { + int len = (ps.bufend > 0) ? ps.bufend : buf.length; + int off = ps.ioff; + while (off < len) { + if ((buf[off] != (byte) ' ') + && (buf[off] != (byte) '\t') + && (buf[off] != (byte) ps.separator)) { + ps.ioff = off; + return off; + } + off++; + } + return off; + } + + /** + * Parse list of items, taking care of quotes and optional LWS. + * The output offset points to the next element of the list. + * @eturn The starting location (i.e. ps.start value), or + * -1 if no item available (end of list). + */ + + public static final int nextItem(byte buf[], ParseState ps) { + // Skip leading spaces, if needed: + int off = -1; + int len = -1; + if ( ps.isSkipable ) + ps.start = off = skipSpaces(buf, ps) ; + else + ps.start = off = ps.ioff ; + len = (ps.bufend > 0) ? ps.bufend : buf.length; + if ( debug ) + System.out.println("parsing: ["+new String(buf, 0, off, len-off)+ + "]"); + // Parse ! + if ( off >= len ) + return -1; + // Setup for parsing, and parse + ps.start = off; + loop: + while (off < len) { + if ( buf[off] == (byte) '"' ) { + // A quoted item, read as one chunk + off++; + while (off < len ) { + if (buf[off] == (byte) '\\') { + off += 2; + } else if (buf[off] == (byte) '"') { + off++; + continue loop; + } else { + off++; + } + } + if ( off == len ) + error("nextItem", "Un-terminated quoted item."); + } else if ((buf[off] == ps.separator) + || (ps.spaceIsSep + && ((buf[off] == ' ') || (buf[off] == '\t')))) { + break loop; + } + off++; + } + ps.end = off; + // Item start is set, we are right at the end of item + if ( ps.isSkipable ) { + ps.ioff = off ; + ps.ooff = skipSpaces(buf, ps); + } + // Check for either the end of the list, or the separator: + if (ps.ooff < ps.bufend) { + if (buf[ps.ooff] == (byte) ps.separator) + ps.ooff++; + } + if ( debug ) + System.out.println("nextItem = ["+new String(buf, 0, ps.start, + ps.end-ps.start)+"]"); + return (ps.end > ps.start) ? ps.start : -1; + } + + public static double parseQuality(byte buf[], ParseState ps) { + // Skip spaces if needed + int off = -1; + if ( ps.isSkipable ) + ps.start = off = skipSpaces(buf, ps); + else + ps.start = off = ps.ioff; + // Parse the integer from byte[] straight (without creating Strings) + int len = (ps.bufend > 0) ? ps.bufend : buf.length; + String str = new String(buf, 0, off, len-off); + try { + return Double.valueOf(str).doubleValue(); + } catch (Exception ex) { + error("parseQuality", "Invalid floating point number."); + } + // Not reached: + return 1.0; + } + +} diff --git a/org/w3c/www/http/HttpParserException.java b/org/w3c/www/http/HttpParserException.java new file mode 100644 index 000000000..2373ad18a --- /dev/null +++ b/org/w3c/www/http/HttpParserException.java @@ -0,0 +1,16 @@ +// HttpParserException.java +// $Id$ +// (c) COPYRIGHT MIT and INRIA, 1996. +// Please first read the full copyright statement in file COPYRIGHT.html + +package org.w3c.www.http; + +import org.w3c.www.mime.MimeParserException; + +public class HttpParserException extends MimeParserException { + + public HttpParserException(String msg) { + super(msg); + } + +} diff --git a/org/w3c/www/http/ParseState.java b/org/w3c/www/http/ParseState.java new file mode 100644 index 000000000..86f7cf414 --- /dev/null +++ b/org/w3c/www/http/ParseState.java @@ -0,0 +1,44 @@ +// ParseState.java +// $Id$ +// (c) COPYRIGHT MIT and INRIA, 1996. +// Please first read the full copyright statement in file COPYRIGHT.html + +package org.w3c.www.http; + +class ParseState { + int ioff = -1; // input offset + int ooff = -1; // output ofset (where parsing should continue) + int start = -1 ; // Start of parsed item (if needed) + int end = -1; // End of parsed item (if needed) + int bufend = -1 ; // End of the buffer to parse + + boolean isSkipable = true ; // Always skip space when this make sense + boolean isQuotable = true ; // Support quted string while parsing next item + boolean spaceIsSep = true; + + byte separator = (byte) ','; // Separator for parsing list + + final void prepare() { + ioff = ooff; + start = -1; + end = -1; + } + + final void prepare(ParseState ps) { + this.ioff = ps.start; + this.bufend = ps.end; + } + + ParseState(int ioff) { + this.ioff = ioff; + } + + ParseState(int ioff, int bufend) { + this.ioff = ioff; + this.bufend = bufend; + } + + ParseState() { + } + +} diff --git a/org/w3c/www/mime/MimeParserException.java b/org/w3c/www/mime/MimeParserException.java new file mode 100644 index 000000000..aabfa1e43 --- /dev/null +++ b/org/w3c/www/mime/MimeParserException.java @@ -0,0 +1,14 @@ +// MimeParserException.java +// $Id$ +// (c) COPYRIGHT MIT and INRIA, 1996. +// Please first read the full copyright statement in file COPYRIGHT.html + +package org.w3c.www.mime; + +public class MimeParserException extends Exception { + + public MimeParserException(String msg) { + super(msg); + } + +}