summaryrefslogtreecommitdiffstats
path: root/simple/simple-http/src/main/java/org/simpleframework/http/message/RequestConsumer.java
diff options
context:
space:
mode:
Diffstat (limited to 'simple/simple-http/src/main/java/org/simpleframework/http/message/RequestConsumer.java')
-rw-r--r--simple/simple-http/src/main/java/org/simpleframework/http/message/RequestConsumer.java457
1 files changed, 457 insertions, 0 deletions
diff --git a/simple/simple-http/src/main/java/org/simpleframework/http/message/RequestConsumer.java b/simple/simple-http/src/main/java/org/simpleframework/http/message/RequestConsumer.java
new file mode 100644
index 0000000..0687271
--- /dev/null
+++ b/simple/simple-http/src/main/java/org/simpleframework/http/message/RequestConsumer.java
@@ -0,0 +1,457 @@
+/*
+ * RequestConsumer.java February 2001
+ *
+ * Copyright (C) 2001, Niall Gallagher <niallg@users.sf.net>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package org.simpleframework.http.message;
+
+import java.util.List;
+
+import org.simpleframework.http.Address;
+import org.simpleframework.http.Path;
+import org.simpleframework.http.Query;
+import org.simpleframework.http.parse.AddressParser;
+
+/**
+ * The <code>RequestConsumer</code> object is used to parse the HTTP
+ * request line followed by the HTTP message headers. This parses the
+ * request URI such that the query parameters and path are extracted
+ * and normalized. It performs this using external parsers, which
+ * will remove and escaped characters and normalize the path segments.
+ * Finally this exposes the HTTP version used using the major and
+ * minor numbers sent with the HTTP request.
+ *
+ * @author Niall Gallagher
+ */
+public class RequestConsumer extends HeaderConsumer {
+
+ /**
+ * This is the address parser used to parse the request URI.
+ */
+ protected AddressParser parser;
+
+ /**
+ * This is the method token send with the HTTP request header.
+ */
+ protected String method;
+
+ /**
+ * This represents the raw request URI in an unparsed form.
+ */
+ protected String target;
+
+ /**
+ * This is the major version number of the HTTP request header.
+ */
+ protected int major;
+
+ /**
+ * This is the minor version number of the HTTP request header.
+ */
+ protected int minor;
+
+ /**
+ * Constructor for the <code>RequestConsumer</code> object. This
+ * is used to create a consumer which can consume a HTTP request
+ * header and provide the consumed contents via a known interface.
+ * This also further breaks down the request URI for convenience.
+ */
+ public RequestConsumer() {
+ super();
+ }
+
+ /**
+ * This can be used to get the target specified for this HTTP
+ * request. This corresponds to the URI sent in the request
+ * line. Typically this will be the path part of the URI, but
+ * can be the full URI if the request is a proxy request.
+ *
+ * @return the target URI that this HTTP request specifies
+ */
+ public String getTarget() {
+ return target;
+ }
+
+ /**
+ * This is used to acquire the address from the request line.
+ * An address is the full URI including the scheme, domain,
+ * port and the query parts. This allows various parameters
+ * to be acquired without having to parse the target.
+ *
+ * @return this returns the address of the request line
+ */
+ public Address getAddress() {
+ if(parser == null) {
+ parser = new AddressParser(target);
+ }
+ return parser;
+ }
+
+ /**
+ * This method is used to acquire the query part from the
+ * HTTP request URI target. This will return only the values
+ * that have been extracted from the request URI target.
+ *
+ * @return the query associated with the HTTP target URI
+ */
+ public Query getQuery() {
+ return getAddress().getQuery();
+ }
+
+ /**
+ * This is used to acquire the path as extracted from the
+ * the HTTP request URI. The <code>Path</code> object that is
+ * provided by this method is immutable, it represents the
+ * normalized path only part from the request URI.
+ *
+ * @return this returns the normalized path for the request
+ */
+ public Path getPath() {
+ return getAddress().getPath();
+ }
+
+ /**
+ * This can be used to get the HTTP method for this request. The
+ * HTTP specification RFC 2616 specifies the HTTP request methods
+ * in section 9, Method Definitions. Typically this will be a
+ * GET or POST method, but can be any valid alphabetic token.
+ *
+ * @return the HTTP method that this request has specified
+ */
+ public String getMethod() {
+ return method;
+ }
+
+ /**
+ * This can be used to get the major number from a HTTP version.
+ * The major version corrosponds to the major protocol type, that
+ * is the 1 of a HTTP/1.0 version string. Typically the major
+ * type is 1, by can be 0 for HTTP/0.9 clients.
+ *
+ * @return the major version number for the HTTP message
+ */
+ public int getMajor() {
+ return major;
+ }
+
+ /**
+ * This can be used to get the minor number from a HTTP version.
+ * The minor version corrosponds to the minor protocol type, that
+ * is the 0 of a HTTP/1.0 version string. This number is typically
+ * used to determine whether persistent connections are supported.
+ *
+ * @return the minor version number for the HTTP message
+ */
+ public int getMinor() {
+ return minor;
+ }
+
+ /**
+ * This can be used to get the date of the first message header
+ * that has the specified name. This is a convenience method that
+ * avoids having to deal with parsing the value of the requested
+ * HTTP message header. This returns -1 if theres no HTTP header
+ * value for the specified name.
+ *
+ * @param name the HTTP message header to get the value from
+ *
+ * @return this returns the date as a long from the header value
+ */
+ public long getDate(String name) {
+ return header.getDate(name);
+ }
+
+ /**
+ * This can be used to get the integer of the first message header
+ * that has the specified name. This is a convenience method that
+ * avoids having to deal with parsing the value of the requested
+ * HTTP message header. This returns -1 if theres no HTTP header
+ * value for the specified name.
+ *
+ * @param name the HTTP message header to get the value from
+ *
+ * @return this returns the date as a long from the header value
+ */
+ public int getInteger(String name) {
+ return header.getInteger(name);
+ }
+
+ /**
+ * This method is used to get a <code>List</code> of the names
+ * for the headers. This will provide the original names for the
+ * HTTP headers for the message. Modifications to the provided
+ * list will not affect the header, the list is a simple copy.
+ *
+ * @return this returns a list of the names within the header
+ */
+ public List<String> getNames() {
+ return header.getNames();
+ }
+
+ /**
+ * This method is invoked after the terminal token has been read.
+ * It is used to process the consumed data and is typically used to
+ * parse the input such that it can be used by the subclass for
+ * some useful puropse. This is called only once by the consumer.
+ */
+ @Override
+ protected void process() {
+ method();
+ target();
+ version();
+ end();
+ headers();
+ }
+
+ /**
+ * This will parse URI target from the first line of the header
+ * and store the parsed string internally. The target token is
+ * used to create an <code>Address</code> object which provides
+ * all the details of the target including the query part.
+ */
+ private void target() {
+ Token token = new Token(array, pos, 0);
+
+ while(pos < count){
+ if(white(array[pos])){
+ pos++;
+ break;
+ }
+ token.size++;
+ pos++;
+ }
+ target = token.toString();
+ }
+
+ /**
+ * This will parse HTTP method from the first line of the header
+ * and store the parsed string internally. The method is used to
+ * determine what action to take with the request, it also acts
+ * as a means to determine the semantics of the request.
+ */
+ private void method() {
+ Token token = new Token(array, pos, 0);
+
+ while(pos < count){
+ if(white(array[pos])){
+ pos++;
+ break;
+ }
+ token.size++;
+ pos++;
+ }
+ method = token.toString();
+ }
+
+ /**
+ * This will parse HTTP version from the first line of the header
+ * and store the parsed string internally. The method is used to
+ * determine what version of HTTP is being used. Typically this
+ * will be HTTP/1.1 however HTTP/1.0 must be supported and this
+ * has different connection semantics with regards to pipelines.
+ */
+ protected void version() {
+ pos += 5; /* "HTTP/" */
+ major(); /* "1" */
+ pos++; /* "." */
+ minor(); /* "1" */
+ }
+
+ /**
+ * This will parse the header from the current offset and convert
+ * the bytes found into an int as it parses the digits it comes
+ * accross. This will cease to parse bytes when it encounters a
+ * non digit byte or the end of the readable bytes.
+ */
+ private void major() {
+ while(pos < count){
+ if(!digit(array[pos])){
+ break;
+ }
+ major *= 10;
+ major += array[pos];
+ major -= '0';
+ pos++;
+ }
+ }
+
+ /**
+ * This will parse the header from the current offset and convert
+ * the bytes found into an int as it parses the digits it comes
+ * accross. This will cease to parse bytes when it encounters a
+ * non digit byte or the end of the readable bytes.
+ */
+ private void minor() {
+ while(pos < count){
+ if(!digit(array[pos])){
+ break;
+ }
+ minor *= 10;
+ minor += array[pos];
+ minor -= '0';
+ pos++;
+ }
+ }
+
+ /**
+ * This is used to determine if a given ISO-8859-1 byte is a digit
+ * character, between an ISO-8859-1 0 and 9. If it is, this will
+ * return true otherwise it returns false.
+ *
+ * @param octet this is to be checked to see if it is a digit
+ *
+ * @return true if the byte is a digit character, false otherwise
+ */
+ protected boolean digit(byte octet) {
+ return octet >= '0' && octet <= '9';
+ }
+
+ /**
+ * This method returns a <code>CharSequence</code> holding the data
+ * consumed for the request. A character sequence is returned as it
+ * can provide a much more efficient means of representing the header
+ * data by just wrapping the consumed byte array.
+ *
+ * @return this returns the characters consumed for the header
+ */
+ public CharSequence getHeader() {
+ return new Token(array, 0, count);
+ }
+
+ /**
+ * This is used to convert the byte range to a string. This
+ * will use UTF-8 encoding for the string which is compatible
+ * with the HTTP default header encoding of ISO-8859-1.
+ *
+ * @return the encoded string representing the token
+ */
+ public String toString() {
+ return getHeader().toString();
+ }
+
+ /**
+ * This is a sequence of characters representing the header data
+ * consumed. Here the internal byte buffer is simply wrapped so
+ * that it can be a represented as a <code>CharSequence</code>.
+ * Wrapping the consumed array in this manner ensures that no
+ * further memory allocation is required.
+ */
+ private static class Token implements CharSequence {
+
+ /**
+ * This is the array that contains the header bytes.
+ */
+ public byte[] array;
+
+ /**
+ * This is the number of bytes to use from the array.
+ */
+ public int size;
+
+ /**
+ * This is the offset in the array the token begins at.
+ */
+ public int off;
+
+ /**
+ * Constructor for the <code>ByteSequence</code> object. This
+ * is used to represent the data that has been consumed by
+ * the header. It acts as a light weight wrapper for the data
+ * and avoids having to create new strings for each event.
+ *
+ * @param array this is the array representing the header
+ * @param off the starting offset for the token range
+ * @param size the number of bytes used for the token
+ */
+ private Token(byte[] array, int off, int size) {
+ this.array = array;
+ this.size = size;
+ this.off = off;
+ }
+
+ /**
+ * This returns the length of the header in bytes. The length
+ * includes the request line and all of the control characters
+ * including the carriage return and line feed at the end of
+ * the request header.
+ *
+ * @return this returns the number of bytes for the header
+ */
+ public int length() {
+ return size;
+ }
+
+ /**
+ * This is used to acquire the character at the specified index.
+ * Characters returned from this method are simply the bytes
+ * casted to a character. This may not convert the character
+ * correctly and a more sensible method should be used.
+ *
+ * @param index the index to extract the character from
+ *
+ * @return this returns the character found at the index
+ */
+ public char charAt(int index) {
+ return (char) array[index];
+ }
+
+ /**
+ * This returns a section of characters within the specified
+ * range. Acquiring a section in this manner is simply done by
+ * setting a start and end offset within the internal array.
+ *
+ * @param start this is the start index to be used
+ * @param end this is the end index to be used
+ *
+ * @return this returns a new sequence within the original
+ */
+ public CharSequence subSequence(int start, int end) {
+ return new Token(array, start, end - start);
+ }
+
+ /**
+ * This is used to create a string from the header bytes. This
+ * converts the header bytes to a string using a compatible
+ * encoding. This may produce different results depending on
+ * the time it is invoked, as the header consumes more data.
+ *
+ * @return this returns an encoded version of the header
+ */
+ public String toString() {
+ return toString("UTF-8");
+ }
+
+ /**
+ * This is used to create a string from the header bytes. This
+ * converts the header bytes to a string using a compatible
+ * encoding. This may produce different results depending on
+ * the time it is invoked, as the header consumes more data.
+ *
+ * @param charset this is the encoding to use for the header
+ *
+ * @return this returns an encoded version of the header
+ */
+ public String toString(String charset) {
+ try {
+ return new String(array, off, size, charset);
+ } catch(Exception e) {
+ return null;
+ }
+ }
+ }
+}
+
+