You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by tr...@apache.org on 2007/11/06 09:59:44 UTC
svn commit: r592337 [1/7] - in /mina/sandbox/asyncweb:
core/src/main/java/org/safehaus/asyncweb/codec/
core/src/main/java/org/safehaus/asyncweb/codec/decoder/
core/src/main/java/org/safehaus/asyncweb/codec/decoder/support/
core/src/main/java/org/safeha...
Author: trustin
Date: Tue Nov 6 00:59:36 2007
New Revision: 592337
URL: http://svn.apache.org/viewvc?rev=592337&view=rev
Log:
* Fixed more compilation warnings
* Reformatted code
Modified:
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/HttpCodecUtils.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/HttpServerCodecFactory.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/CRLFDecodingState.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/ChunkedBodyDecodingState.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/HttpDecoderException.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/HttpHeaderDecodingState.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/HttpRequestDecodingState.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/HttpRequestLineDecodingState.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/support/ConsumeToCRLFDecodingState.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/support/ConsumeToDynamicTerminatorDecodingState.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/support/ConsumeToLinearWhitespaceDecodingState.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/support/ConsumeToTerminatorDecodingState.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/support/DecodingState.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/support/DecodingStateMachine.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/support/FixedLengthDecodingState.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/support/LinearWhitespaceSkippingState.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/support/SkippingState.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/support/StateMachineProtocolDecoder.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/encoder/CompatibilityCookieEncoder.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/encoder/CookieEncoder.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/encoder/OneShotHttpResponseEncoder.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/common/Content.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/common/Cookie.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/common/CookieComparator.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/common/DefaultCookie.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/common/DefaultHttpMessage.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/common/DefaultHttpRequest.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/common/DefaultHttpResponse.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/common/HeaderNameComparator.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/common/HttpMessage.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/common/HttpMethod.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/common/HttpRequest.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/common/HttpResponse.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/common/HttpResponseStatus.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/common/HttpVersion.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/common/MutableCookie.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/common/MutableHttpMessage.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/common/MutableHttpRequest.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/common/MutableHttpResponse.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/common/content/ByteBufferContent.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/common/content/EmptyContent.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/BasicServiceContainer.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/ContainerLifecycleException.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/HttpService.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/HttpServiceContext.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/HttpServiceFilter.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/HttpServiceHandler.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/HttpSession.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/ServiceContainer.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/Transport.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/TransportException.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/context/AbstractHttpServiceContext.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/context/BasicKeepAliveStrategy.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/context/CounterKeepAliveStrategy.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/context/KeepAliveStrategy.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/errorReporting/CSS.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/errorReporting/ErrorResponseFormatter.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/errorReporting/StandardResponseFormatter.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/filter/SessionKeepAliveFilter.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/filter/ThreadPoolFilter.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/pipeline/RequestPipeline.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/pipeline/RequestPipelineListener.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/pipeline/StandardRequestPipeline.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/resolver/CompositeResolver.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/resolver/ExactMatchURIServiceResolver.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/resolver/FixedServiceResolver.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/resolver/PassThruResolver.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/resolver/ServiceResolver.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/resolver/SimplePrefixResolver.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/session/BasicSession.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/session/BasicSessionStore.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/session/CookieIdentifier.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/session/DefaultSessionAccessor.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/session/HttpSessionAccessor.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/session/HttpSessionIdentifier.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/session/HttpSessionKeyFactory.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/session/HttpSessionListener.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/session/HttpSessionStore.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/session/LoggingSessionListener.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/session/SecureRandomKeyFactory.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/transport/mina/DefaultHttpIoHandler.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/transport/mina/HttpIoHandler.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/transport/mina/LoggingExceptionMonitor.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/transport/mina/MinaTransport.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/service/transport/mina/SingleHttpSessionIoHandler.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/util/HttpDateFormat.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/util/HttpHeaderConstants.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/util/LinkedPermitIssuer.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/util/PermitExpirationListener.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/util/StringBundle.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/util/TimedPermit.java
mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/util/TimedPermitIssuer.java
mina/sandbox/asyncweb/core/src/test/java/org/safehaus/asyncweb/common/DefaultHttpRequestTest.java
mina/sandbox/asyncweb/core/src/test/java/org/safehaus/asyncweb/service/filter/resolver/DummyResolver.java
mina/sandbox/asyncweb/core/src/test/java/org/safehaus/asyncweb/service/filter/resolver/ExactMatchURIServiceResolverTest.java
mina/sandbox/asyncweb/core/src/test/java/org/safehaus/asyncweb/service/filter/resolver/SimplePrefixResolverTest.java
mina/sandbox/asyncweb/core/src/test/java/org/safehaus/asyncweb/util/LinkedPermitIssuerTest.java
mina/sandbox/asyncweb/core/src/test/java/org/safehaus/asyncweb/util/MockNextFilter.java
mina/sandbox/asyncweb/example/src/main/java/org/safehaus/asyncweb/example/cookie/CookieExample.java
mina/sandbox/asyncweb/example/src/main/java/org/safehaus/asyncweb/example/helloworld/HelloWorldHttpService.java
mina/sandbox/asyncweb/example/src/main/java/org/safehaus/asyncweb/example/lightweight/HttpProtocolHandler.java
mina/sandbox/asyncweb/example/src/main/java/org/safehaus/asyncweb/example/lightweight/Main.java
mina/sandbox/asyncweb/example/src/main/java/org/safehaus/asyncweb/example/session/SessionExample.java
mina/sandbox/asyncweb/springframework/src/main/java/org/safehaus/asyncweb/integration/spring/HttpServiceLoader.java
mina/sandbox/asyncweb/springframework/src/main/java/org/safehaus/asyncweb/integration/spring/Main.java
Modified: mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/HttpCodecUtils.java
URL: http://svn.apache.org/viewvc/mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/HttpCodecUtils.java?rev=592337&r1=592336&r2=592337&view=diff
==============================================================================
--- mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/HttpCodecUtils.java (original)
+++ mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/HttpCodecUtils.java Tue Nov 6 00:59:36 2007
@@ -29,306 +29,306 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
public class HttpCodecUtils {
- /**
- * The default charset we employ
- */
- public static final String DEFAULT_CHARACTER_ENCODING="ISO-8859-1";
-
- /**
- * Ampersand character
- */
- public static final byte AMP = 38;
-
- /**
- * Colon character
- */
- public static final byte COLON = 58;
-
- /**
- * Carriage return character
- */
- public static final byte CR = 13;
-
- /**
- * Equals character
- */
- public static final byte EQUALS = 61;
-
- /**
- * Line feed character
- */
- public static final byte LF = 10;
-
- /**
- * Space character
- */
- public static final byte SP = 32;
-
- /**
- * Plus character
- */
- public static final byte PLUS = 43;
-
- /**
- * Question mark character
- */
- public static final byte QS = 63;
-
- /**
- * Horizontal tab character
- */
- public static final byte HT = 9;
-
- /**
- * Percent character
- */
- public static final byte PERCENT = 37;
-
- /**
- * Foward-slash character
- */
- public static final byte FOWARD_SLASH = 47;
-
- /**
- * Back-slash character
- */
- public static final byte BACK_SLASH = 92;
-
- /**
- * Quote character
- */
- public static final byte QUOTE = 34;
-
- /**
- * Semi-colon
- */
- public static final byte SEMI_COLON = 59;
-
- /**
- * Bytes making up a <code>CR LF</code>
- */
- private static final byte[] CRLF_BYTES = new byte[] {CR, LF};
-
-
- private static final String US_ASCII_CHARSET_NAME = "US-ASCII";
-
- /**
- * A lookup table for HTPP separator characters
- */
- private static boolean[] HTTP_SEPARATORS = new boolean[128];
-
- /**
- * A lookup table for HTTP control characters
- */
- private static boolean[] HTTP_CONTROLS = new boolean[128];
-
- /**
- * A lookup table from ASCII char values to corresponding decimal values
- */
- private static final int[] HEX_DEC = {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 00, 01, 02, 03, 04, 05, 06, 07, 8, 9, -1, -1, -1, -1, -1, -1,
- -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- };
-
- private static final Logger LOG = LoggerFactory.getLogger(HttpCodecUtils.class);
-
- /**
- * Determines whether a specified (US-ASCII) character is a
- * valid hex character:
- * <ul>
- * <li>A..F</li>
- * <li>a..f</li>
- * <li>0..9</li>
- * </ul>
- *
- * @param b The character to check
- * @return <code>true</code> iff the character is a valid hex
- * character
- */
- public static boolean isHex(byte b) {
- return HEX_DEC[b] != -1;
- }
-
- /**
- * Determines whether a specified (US-ASCII) character is an
- * HTTP field separator
- *
- * @param b the US-ASCII character to check
- * @return <code>true</code> iff the character is an HTTP field
- * separator
- */
- public static boolean isHttpSeparator(byte b) {
- return HTTP_SEPARATORS[b];
- }
-
- /**
- * Determines whether a specified (US-ASCII) character is an
- * HTTP control character
- *
- * @param b the US-ASCII character to check
- * @return <code>true</code> iff the character is an HTTP control
- * character
- */
- public static boolean isHttpControl(byte b) {
- return HTTP_CONTROLS[b];
- }
-
- /**
- * Determines whether a specified (US-ASCII) character is an HTTP
- * whitespace character (Space or Horizontal tab)
- *
- * @param b the US-ASCII character to check
- * @return <code>true</code> iff the character is an HTTP whitespace
- * character
- */
- public static boolean isWhiteSpace(byte b) {
- return b == SP || b == HT;
- }
-
- /**
- * "Pushes back" a byte on to the specified buffer, by rewinding the
- * position by 1 byte
- *
- * @param buffer The buffer to "push back" to
- */
- public static void pushBack(IoBuffer buffer) {
- buffer.position(buffer.position() - 1);
- }
-
- /**
- * Obtains the decimal value for a hex value encoded in ASCII
- *
- * @param b The ASCII encoded byte
- * @return The decimal value - or <code>-1</code> if the specified byte
- * is not a valid ASCII hex character
- */
- public static int hexASCIIToDecimal(byte b) {
- return HEX_DEC[b];
- }
-
- /**
- * Returns the ASCII bytes for a specified string.
- *
- * @param str The string
- * @return The ASCII bytes making up the string
- */
- public static byte[] getASCIIBytes(String str) {
- try {
- return str.getBytes(US_ASCII_CHARSET_NAME);
- } catch (UnsupportedEncodingException e) {
- throw new IllegalStateException("Required charset: " + US_ASCII_CHARSET_NAME);
- }
- }
-
- /**
- * Throws a {@link HttpDecoderException} with a specified cause.
- * This method should be used when the request is badly formed.
- *
- * @param cause The cause
- */
- public static void throwDecoderException(String cause) throws ProtocolDecoderException {
- throwDecoderException(cause, HttpResponseStatus.BAD_REQUEST);
- }
-
- /**
- * Throws a {@link HttpDecoderException} with a specified response
- * status
- *
- * @param message The cause
- * @param status The response status
- */
- public static void throwDecoderException(String message, HttpResponseStatus status) throws ProtocolDecoderException {
- if (!(status.getCategory() == Category.CLIENT_ERROR ||
- status.getCategory() == Category.SERVER_ERROR)) {
- throw new IllegalArgumentException("Cant fail with successful response");
- }
- if (LOG.isInfoEnabled()) {
- LOG.info("Decode failure. Cause: " + message);
- }
- throw new HttpDecoderException(message, status);
- }
-
- /**
- * Appends a string to a specified {@link IoBuffer}.
- * This method assumes ascii encoding and is primarily used for encoding
- * http header names and values.<br/>
- * Note that encoding header values this way is not stricly correct
- * (character encodings). However, existing containers do it this way
- * (e.g. Tomcat), and we're probably safer doing it a similar way for the
- * time being
- *
- * @param buffer The buffer to append to
- * @param string The string to append
- */
- public static void appendString(IoBuffer buffer, String string) {
- if (string == null) {
- return;
- }
- int len = string.length();
-
- for (int i = 0; i < len; i++) {
- byte b = (byte)string.charAt (i);
- if (isHttpControl(b) && b != HT) {
- b = SP;
- }
- buffer.put(b);
- }
- }
-
- /**
- * Appends a <code>CR LF</code> to the specified buffer
- *
- * @param buffer The buffer
- */
- public static void appendCRLF(IoBuffer buffer) {
- buffer.put(CRLF_BYTES);
- }
-
- static {
- // HTTP Separator characters
- HTTP_SEPARATORS[34] = true; // "
- HTTP_SEPARATORS[40] = true; // )
- HTTP_SEPARATORS[41] = true; // (
- HTTP_SEPARATORS[44] = true; // ,
- HTTP_SEPARATORS[47] = true; // /
- HTTP_SEPARATORS[58] = true; // :
- HTTP_SEPARATORS[59] = true; // ;
- HTTP_SEPARATORS[60] = true; // <
- HTTP_SEPARATORS[61] = true; // =
- HTTP_SEPARATORS[62] = true; // >
- HTTP_SEPARATORS[63] = true; // ?
- HTTP_SEPARATORS[64] = true; // @
- HTTP_SEPARATORS[91] = true; // [
- HTTP_SEPARATORS[93] = true; // ]
- HTTP_SEPARATORS[92] = true; // \
- HTTP_SEPARATORS[123] = true; // {
- HTTP_SEPARATORS[125] = true; // }
- // TODO: SP, HT
-
- // HTTP Control characters
- for (int i=0; i<=31; ++i) {
- HTTP_CONTROLS[i] = true;
- }
- HTTP_CONTROLS[127] = true; // DEL
-
- }
+ /**
+ * The default charset we employ
+ */
+ public static final String DEFAULT_CHARACTER_ENCODING = "ISO-8859-1";
+
+ /**
+ * Ampersand character
+ */
+ public static final byte AMP = 38;
+
+ /**
+ * Colon character
+ */
+ public static final byte COLON = 58;
+
+ /**
+ * Carriage return character
+ */
+ public static final byte CR = 13;
+
+ /**
+ * Equals character
+ */
+ public static final byte EQUALS = 61;
+
+ /**
+ * Line feed character
+ */
+ public static final byte LF = 10;
+
+ /**
+ * Space character
+ */
+ public static final byte SP = 32;
+
+ /**
+ * Plus character
+ */
+ public static final byte PLUS = 43;
+
+ /**
+ * Question mark character
+ */
+ public static final byte QS = 63;
+
+ /**
+ * Horizontal tab character
+ */
+ public static final byte HT = 9;
+
+ /**
+ * Percent character
+ */
+ public static final byte PERCENT = 37;
+
+ /**
+ * Foward-slash character
+ */
+ public static final byte FOWARD_SLASH = 47;
+
+ /**
+ * Back-slash character
+ */
+ public static final byte BACK_SLASH = 92;
+
+ /**
+ * Quote character
+ */
+ public static final byte QUOTE = 34;
+
+ /**
+ * Semi-colon
+ */
+ public static final byte SEMI_COLON = 59;
+
+ /**
+ * Bytes making up a <code>CR LF</code>
+ */
+ private static final byte[] CRLF_BYTES = new byte[] { CR, LF };
+
+ private static final String US_ASCII_CHARSET_NAME = "US-ASCII";
+
+ /**
+ * A lookup table for HTPP separator characters
+ */
+ private static boolean[] HTTP_SEPARATORS = new boolean[128];
+
+ /**
+ * A lookup table for HTTP control characters
+ */
+ private static boolean[] HTTP_CONTROLS = new boolean[128];
+
+ /**
+ * A lookup table from ASCII char values to corresponding decimal values
+ */
+ private static final int[] HEX_DEC = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 00, 01, 02, 03, 04, 05, 06, 07, 8, 9, -1, -1,
+ -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, };
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(HttpCodecUtils.class);
+
+ /**
+ * Determines whether a specified (US-ASCII) character is a
+ * valid hex character:
+ * <ul>
+ * <li>A..F</li>
+ * <li>a..f</li>
+ * <li>0..9</li>
+ * </ul>
+ *
+ * @param b The character to check
+ * @return <code>true</code> iff the character is a valid hex
+ * character
+ */
+ public static boolean isHex(byte b) {
+ return HEX_DEC[b] != -1;
+ }
+
+ /**
+ * Determines whether a specified (US-ASCII) character is an
+ * HTTP field separator
+ *
+ * @param b the US-ASCII character to check
+ * @return <code>true</code> iff the character is an HTTP field
+ * separator
+ */
+ public static boolean isHttpSeparator(byte b) {
+ return HTTP_SEPARATORS[b];
+ }
+
+ /**
+ * Determines whether a specified (US-ASCII) character is an
+ * HTTP control character
+ *
+ * @param b the US-ASCII character to check
+ * @return <code>true</code> iff the character is an HTTP control
+ * character
+ */
+ public static boolean isHttpControl(byte b) {
+ return HTTP_CONTROLS[b];
+ }
+
+ /**
+ * Determines whether a specified (US-ASCII) character is an HTTP
+ * whitespace character (Space or Horizontal tab)
+ *
+ * @param b the US-ASCII character to check
+ * @return <code>true</code> iff the character is an HTTP whitespace
+ * character
+ */
+ public static boolean isWhiteSpace(byte b) {
+ return b == SP || b == HT;
+ }
+
+ /**
+ * "Pushes back" a byte on to the specified buffer, by rewinding the
+ * position by 1 byte
+ *
+ * @param buffer The buffer to "push back" to
+ */
+ public static void pushBack(IoBuffer buffer) {
+ buffer.position(buffer.position() - 1);
+ }
+
+ /**
+ * Obtains the decimal value for a hex value encoded in ASCII
+ *
+ * @param b The ASCII encoded byte
+ * @return The decimal value - or <code>-1</code> if the specified byte
+ * is not a valid ASCII hex character
+ */
+ public static int hexASCIIToDecimal(byte b) {
+ return HEX_DEC[b];
+ }
+
+ /**
+ * Returns the ASCII bytes for a specified string.
+ *
+ * @param str The string
+ * @return The ASCII bytes making up the string
+ */
+ public static byte[] getASCIIBytes(String str) {
+ try {
+ return str.getBytes(US_ASCII_CHARSET_NAME);
+ } catch (UnsupportedEncodingException e) {
+ throw new IllegalStateException("Required charset: "
+ + US_ASCII_CHARSET_NAME);
+ }
+ }
+
+ /**
+ * Throws a {@link HttpDecoderException} with a specified cause.
+ * This method should be used when the request is badly formed.
+ *
+ * @param cause The cause
+ */
+ public static void throwDecoderException(String cause)
+ throws ProtocolDecoderException {
+ throwDecoderException(cause, HttpResponseStatus.BAD_REQUEST);
+ }
+
+ /**
+ * Throws a {@link HttpDecoderException} with a specified response
+ * status
+ *
+ * @param message The cause
+ * @param status The response status
+ */
+ public static void throwDecoderException(String message,
+ HttpResponseStatus status) throws ProtocolDecoderException {
+ if (!(status.getCategory() == Category.CLIENT_ERROR || status
+ .getCategory() == Category.SERVER_ERROR)) {
+ throw new IllegalArgumentException(
+ "Cant fail with successful response");
+ }
+ if (LOG.isInfoEnabled()) {
+ LOG.info("Decode failure. Cause: " + message);
+ }
+ throw new HttpDecoderException(message, status);
+ }
+
+ /**
+ * Appends a string to a specified {@link IoBuffer}.
+ * This method assumes ascii encoding and is primarily used for encoding
+ * http header names and values.<br/>
+ * Note that encoding header values this way is not stricly correct
+ * (character encodings). However, existing containers do it this way
+ * (e.g. Tomcat), and we're probably safer doing it a similar way for the
+ * time being
+ *
+ * @param buffer The buffer to append to
+ * @param string The string to append
+ */
+ public static void appendString(IoBuffer buffer, String string) {
+ if (string == null) {
+ return;
+ }
+ int len = string.length();
+
+ for (int i = 0; i < len; i++) {
+ byte b = (byte) string.charAt(i);
+ if (isHttpControl(b) && b != HT) {
+ b = SP;
+ }
+ buffer.put(b);
+ }
+ }
+
+ /**
+ * Appends a <code>CR LF</code> to the specified buffer
+ *
+ * @param buffer The buffer
+ */
+ public static void appendCRLF(IoBuffer buffer) {
+ buffer.put(CRLF_BYTES);
+ }
+
+ static {
+ // HTTP Separator characters
+ HTTP_SEPARATORS[34] = true; // "
+ HTTP_SEPARATORS[40] = true; // )
+ HTTP_SEPARATORS[41] = true; // (
+ HTTP_SEPARATORS[44] = true; // ,
+ HTTP_SEPARATORS[47] = true; // /
+ HTTP_SEPARATORS[58] = true; // :
+ HTTP_SEPARATORS[59] = true; // ;
+ HTTP_SEPARATORS[60] = true; // <
+ HTTP_SEPARATORS[61] = true; // =
+ HTTP_SEPARATORS[62] = true; // >
+ HTTP_SEPARATORS[63] = true; // ?
+ HTTP_SEPARATORS[64] = true; // @
+ HTTP_SEPARATORS[91] = true; // [
+ HTTP_SEPARATORS[93] = true; // ]
+ HTTP_SEPARATORS[92] = true; // \
+ HTTP_SEPARATORS[123] = true; // {
+ HTTP_SEPARATORS[125] = true; // }
+ // TODO: SP, HT
+
+ // HTTP Control characters
+ for (int i = 0; i <= 31; ++i) {
+ HTTP_CONTROLS[i] = true;
+ }
+ HTTP_CONTROLS[127] = true; // DEL
+
+ }
-
}
Modified: mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/HttpServerCodecFactory.java
URL: http://svn.apache.org/viewvc/mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/HttpServerCodecFactory.java?rev=592337&r1=592336&r2=592337&view=diff
==============================================================================
--- mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/HttpServerCodecFactory.java (original)
+++ mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/HttpServerCodecFactory.java Tue Nov 6 00:59:36 2007
@@ -34,36 +34,38 @@
public class HttpServerCodecFactory implements ProtocolCodecFactory {
- private final Logger log = LoggerFactory.getLogger(getClass());
- private boolean parseCookies = true;
-
- public boolean isParseCookies() {
- return parseCookies;
- }
-
- public void setParseCookies(boolean parseCookies) {
- this.parseCookies = parseCookies;
- }
-
- public ProtocolDecoder getDecoder() throws Exception {
- // TODO Use a parser pool if this performs bad.
-
- HttpRequestDecodingState topLevelState = new HttpRequestDecodingState() {
- @Override
- protected DecodingState finishDecode(List<Object> childProducts, ProtocolDecoderOutput out) throws Exception {
- if (log.isDebugEnabled()) {
- log.debug("Finished decoding a message: " + childProducts);
- }
- out.write(childProducts.get(0));
- return this;
- }
- };
- topLevelState.setParseCookies(parseCookies);
-
- return new StateMachineProtocolDecoder(topLevelState);
- }
-
- public ProtocolEncoder getEncoder() throws Exception {
- return new OneShotHttpResponseEncoder();
- }
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private boolean parseCookies = true;
+
+ public boolean isParseCookies() {
+ return parseCookies;
+ }
+
+ public void setParseCookies(boolean parseCookies) {
+ this.parseCookies = parseCookies;
+ }
+
+ public ProtocolDecoder getDecoder() throws Exception {
+ // TODO Use a parser pool if this performs bad.
+
+ HttpRequestDecodingState topLevelState = new HttpRequestDecodingState() {
+ @Override
+ protected DecodingState finishDecode(List<Object> childProducts,
+ ProtocolDecoderOutput out) throws Exception {
+ if (log.isDebugEnabled()) {
+ log.debug("Finished decoding a message: " + childProducts);
+ }
+ out.write(childProducts.get(0));
+ return this;
+ }
+ };
+ topLevelState.setParseCookies(parseCookies);
+
+ return new StateMachineProtocolDecoder(topLevelState);
+ }
+
+ public ProtocolEncoder getEncoder() throws Exception {
+ return new OneShotHttpResponseEncoder();
+ }
}
Modified: mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/CRLFDecodingState.java
URL: http://svn.apache.org/viewvc/mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/CRLFDecodingState.java?rev=592337&r1=592336&r2=592337&view=diff
==============================================================================
--- mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/CRLFDecodingState.java (original)
+++ mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/CRLFDecodingState.java Tue Nov 6 00:59:36 2007
@@ -24,7 +24,6 @@
import org.safehaus.asyncweb.codec.HttpCodecUtils;
import org.safehaus.asyncweb.codec.decoder.support.DecodingState;
-
/**
* Decodes a single <code>CRLF</code>.
* If it is found, the bytes are consumed and <code>Boolean.TRUE</code>
@@ -33,51 +32,55 @@
* product.
* Note that if we find a CR but do not find a following LF, we raise
* an error.
- *
+ *
* @author irvingd
* @author trustin
* @version $Rev$, $Date$
*/
public abstract class CRLFDecodingState implements DecodingState {
- private boolean hasCR;
-
- public DecodingState decode(IoBuffer in, ProtocolDecoderOutput out) throws Exception {
- boolean found = false;
- boolean finished = false;
- while (in.hasRemaining()) {
- byte b = in.get();
- if (!hasCR) {
- if (b == HttpCodecUtils.CR) {
- hasCR = true;
- } else {
- if (b == HttpCodecUtils.LF) {
- found = true;
- } else {
- in.position(in.position() - 1);
- found = false;
- }
- finished = true;
- break;
+ private boolean hasCR;
+
+ public DecodingState decode(IoBuffer in, ProtocolDecoderOutput out)
+ throws Exception {
+ boolean found = false;
+ boolean finished = false;
+ while (in.hasRemaining()) {
+ byte b = in.get();
+ if (!hasCR) {
+ if (b == HttpCodecUtils.CR) {
+ hasCR = true;
+ } else {
+ if (b == HttpCodecUtils.LF) {
+ found = true;
+ } else {
+ in.position(in.position() - 1);
+ found = false;
+ }
+ finished = true;
+ break;
+ }
+ } else {
+ if (b == HttpCodecUtils.LF) {
+ found = true;
+ finished = true;
+ break;
+ } else {
+ HttpCodecUtils
+ .throwDecoderException("Expected LF after CR but was: "
+ + b);
+ }
+ }
}
- } else {
- if (b == HttpCodecUtils.LF) {
- found = true;
- finished = true;
- break;
+
+ if (finished) {
+ hasCR = false;
+ return finishDecode(found, out);
} else {
- HttpCodecUtils.throwDecoderException("Expected LF after CR but was: " + b);
+ return this;
}
- }
- }
-
- if (finished) {
- hasCR = false;
- return finishDecode(found, out);
- } else {
- return this;
}
- }
-
- protected abstract DecodingState finishDecode(boolean foundCRLF, ProtocolDecoderOutput out) throws Exception;
+
+ protected abstract DecodingState finishDecode(boolean foundCRLF,
+ ProtocolDecoderOutput out) throws Exception;
}
Modified: mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/ChunkedBodyDecodingState.java
URL: http://svn.apache.org/viewvc/mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/ChunkedBodyDecodingState.java?rev=592337&r1=592336&r2=592337&view=diff
==============================================================================
--- mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/ChunkedBodyDecodingState.java (original)
+++ mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/ChunkedBodyDecodingState.java Tue Nov 6 00:59:36 2007
@@ -32,20 +32,19 @@
import org.safehaus.asyncweb.codec.decoder.support.SkippingState;
import org.safehaus.asyncweb.common.HttpResponseStatus;
-
/**
* A decoder which decodes the body of HTTP Requests having
* a "chunked" transfer-coding.
- *
+ *
* This decoder does <i>not</i> decode trailing entity-headers - it simply
- * discards them. Tomcat currently does the same - so this is probably
+ * discards them. Tomcat currently does the same - so this is probably
* the most stable approach for now.<br/>
- * If the need arises to decode them in the future, we simply need to employ a
- * <code>HttpHeaderDecoder</code> following the last chunk - yielding
+ * If the need arises to decode them in the future, we simply need to employ a
+ * <code>HttpHeaderDecoder</code> following the last chunk - yielding
* headers for the encountered trailing entity-headers.<p/>
- *
+ *
* This decoder decodes the following format:
- *
+ *
* <pre>
* Chunked-Body = *chunk
* last-chunk
@@ -60,143 +59,154 @@
* chunk-ext-val = token | quoted-string
* chunk-data = chunk-size(OCTET)
* trailer = *(entity-header CRLF)
- * </pre>
+ * </pre>
*
* <code>ChunkedBodyDecoder</code> employs a <code>SharedBytesAllocator</code>
* to enable the content of each decoded chunk to contribute to a single
* <code>Bytes</code>. This enables all chunks to be read without requiring
* copying.
- *
+ *
* @author irvingd
*/
abstract class ChunkedBodyDecodingState extends DecodingStateMachine {
- private static final Charset US_ASCII = Charset.forName("US-ASCII");
-
- private final CharsetDecoder asciiDecoder = US_ASCII.newDecoder();
- private int lastChunkLength;
- private boolean chunkHasExtension;
-
- ChunkedBodyDecodingState() {
- }
-
- @Override
- protected void destroy() throws Exception {
- }
-
- @Override
- protected DecodingState init() throws Exception {
- chunkHasExtension = false;
- return READ_CHUNK_LENGTH;
- }
-
- private final DecodingState READ_CHUNK_LENGTH = new ConsumeToDynamicTerminatorDecodingState() {
- @Override
- protected DecodingState finishDecode(IoBuffer product, ProtocolDecoderOutput out) throws Exception {
- if (!product.hasRemaining()) {
- HttpCodecUtils.throwDecoderException("Expected a chunk length.");
- }
-
- String length = product.getString(asciiDecoder);
- lastChunkLength = Integer.parseInt(length, 16);
- if (chunkHasExtension) {
- return SKIP_CHUNK_EXTENSION;
- }
- return AFTER_SKIP_CHUNK_EXTENSION.decode( IoBuffer.wrap( new byte[] { HttpCodecUtils.CR } ), out );
- }
+ private static final Charset US_ASCII = Charset.forName("US-ASCII");
- @Override
- protected boolean isTerminator(byte b) {
- if (!(b >= '0' && b <= '9' || b >= 'a' && b <= 'f' || b >= 'A' && b <= 'F')) {
- if (b == HttpCodecUtils.CR || b == HttpCodecUtils.SEMI_COLON) {
- chunkHasExtension = (b == HttpCodecUtils.SEMI_COLON);
- return true;
- }
- throw new IllegalArgumentException();
- }
- return false;
- }
- };
-
- private final DecodingState SKIP_CHUNK_EXTENSION = new SkippingState() {
- @Override
- protected DecodingState finishDecode(int skippedBytes) throws Exception {
- return AFTER_SKIP_CHUNK_EXTENSION;
- }
+ private final CharsetDecoder asciiDecoder = US_ASCII.newDecoder();
- @Override
- protected boolean canSkip(byte b) {
- return (b != HttpCodecUtils.CR);
- }
- };
-
- private final DecodingState AFTER_SKIP_CHUNK_EXTENSION = new CRLFDecodingState() {
- @Override
- protected DecodingState finishDecode(boolean foundCRLF, ProtocolDecoderOutput out) throws Exception {
- if (!foundCRLF) {
- HttpCodecUtils.throwDecoderException(
- "Expected CRLF at the end of chunk extension.",
- HttpResponseStatus.BAD_REQUEST);
- }
-
- if (lastChunkLength <= 0) {
- return FIND_END_OF_TRAILER;
- } else {
- return new FixedLengthDecodingState(lastChunkLength) {
- @Override
- protected DecodingState finishDecode(IoBuffer readData, ProtocolDecoderOutput out) throws Exception {
- out.write(readData);
- // Reset the state.
- lastChunkLength = 0;
- return AFTER_CHUNK_DATA;
- }
- };
- }
- }
- };
-
- private final DecodingState AFTER_CHUNK_DATA = new CRLFDecodingState() {
- @Override
- protected DecodingState finishDecode(boolean foundCRLF, ProtocolDecoderOutput out) throws Exception {
- if (!foundCRLF) {
- HttpCodecUtils.throwDecoderException(
- "Expected CRLF after a chunk data.",
- HttpResponseStatus.BAD_REQUEST);
-
- }
- chunkHasExtension = false;
- return READ_CHUNK_LENGTH;
- }
- };
-
- private final DecodingState FIND_END_OF_TRAILER = new CRLFDecodingState() {
- @Override
- protected DecodingState finishDecode(boolean foundCRLF, ProtocolDecoderOutput out) throws Exception {
- if (foundCRLF) {
- return null; // Finish
- } else {
- return SKIP_ENTITY_HEADER;
- }
- }
- };
-
- private final DecodingState SKIP_ENTITY_HEADER = new SkippingState() {
+ private int lastChunkLength;
- @Override
- protected boolean canSkip(byte b) {
- return (b != HttpCodecUtils.CR);
+ private boolean chunkHasExtension;
+
+ ChunkedBodyDecodingState() {
}
@Override
- protected DecodingState finishDecode(int skippedBytes) throws Exception {
- return AFTER_SKIP_ENTITY_HEADER;
+ protected void destroy() throws Exception {
}
- };
-
- private final DecodingState AFTER_SKIP_ENTITY_HEADER = new CRLFDecodingState() {
+
@Override
- protected DecodingState finishDecode(boolean foundCRLF, ProtocolDecoderOutput out) throws Exception {
- return FIND_END_OF_TRAILER;
+ protected DecodingState init() throws Exception {
+ chunkHasExtension = false;
+ return READ_CHUNK_LENGTH;
}
- };
+
+ private final DecodingState READ_CHUNK_LENGTH = new ConsumeToDynamicTerminatorDecodingState() {
+ @Override
+ protected DecodingState finishDecode(IoBuffer product,
+ ProtocolDecoderOutput out) throws Exception {
+ if (!product.hasRemaining()) {
+ HttpCodecUtils
+ .throwDecoderException("Expected a chunk length.");
+ }
+
+ String length = product.getString(asciiDecoder);
+ lastChunkLength = Integer.parseInt(length, 16);
+ if (chunkHasExtension) {
+ return SKIP_CHUNK_EXTENSION;
+ }
+ return AFTER_SKIP_CHUNK_EXTENSION.decode(IoBuffer
+ .wrap(new byte[] { HttpCodecUtils.CR }), out);
+ }
+
+ @Override
+ protected boolean isTerminator(byte b) {
+ if (!(b >= '0' && b <= '9' || b >= 'a' && b <= 'f' || b >= 'A'
+ && b <= 'F')) {
+ if (b == HttpCodecUtils.CR || b == HttpCodecUtils.SEMI_COLON) {
+ chunkHasExtension = b == HttpCodecUtils.SEMI_COLON;
+ return true;
+ }
+ throw new IllegalArgumentException();
+ }
+ return false;
+ }
+ };
+
+ private final DecodingState SKIP_CHUNK_EXTENSION = new SkippingState() {
+ @Override
+ protected DecodingState finishDecode(int skippedBytes) throws Exception {
+ return AFTER_SKIP_CHUNK_EXTENSION;
+ }
+
+ @Override
+ protected boolean canSkip(byte b) {
+ return b != HttpCodecUtils.CR;
+ }
+ };
+
+ private final DecodingState AFTER_SKIP_CHUNK_EXTENSION = new CRLFDecodingState() {
+ @Override
+ protected DecodingState finishDecode(boolean foundCRLF,
+ ProtocolDecoderOutput out) throws Exception {
+ if (!foundCRLF) {
+ HttpCodecUtils.throwDecoderException(
+ "Expected CRLF at the end of chunk extension.",
+ HttpResponseStatus.BAD_REQUEST);
+ }
+
+ if (lastChunkLength <= 0) {
+ return FIND_END_OF_TRAILER;
+ } else {
+ return new FixedLengthDecodingState(lastChunkLength) {
+ @Override
+ protected DecodingState finishDecode(IoBuffer readData,
+ ProtocolDecoderOutput out) throws Exception {
+ out.write(readData);
+ // Reset the state.
+ lastChunkLength = 0;
+ return AFTER_CHUNK_DATA;
+ }
+ };
+ }
+ }
+ };
+
+ private final DecodingState AFTER_CHUNK_DATA = new CRLFDecodingState() {
+ @Override
+ protected DecodingState finishDecode(boolean foundCRLF,
+ ProtocolDecoderOutput out) throws Exception {
+ if (!foundCRLF) {
+ HttpCodecUtils.throwDecoderException(
+ "Expected CRLF after a chunk data.",
+ HttpResponseStatus.BAD_REQUEST);
+
+ }
+ chunkHasExtension = false;
+ return READ_CHUNK_LENGTH;
+ }
+ };
+
+ private final DecodingState FIND_END_OF_TRAILER = new CRLFDecodingState() {
+ @Override
+ protected DecodingState finishDecode(boolean foundCRLF,
+ ProtocolDecoderOutput out) throws Exception {
+ if (foundCRLF) {
+ return null; // Finish
+ } else {
+ return SKIP_ENTITY_HEADER;
+ }
+ }
+ };
+
+ private final DecodingState SKIP_ENTITY_HEADER = new SkippingState() {
+
+ @Override
+ protected boolean canSkip(byte b) {
+ return b != HttpCodecUtils.CR;
+ }
+
+ @Override
+ protected DecodingState finishDecode(int skippedBytes) throws Exception {
+ return AFTER_SKIP_ENTITY_HEADER;
+ }
+ };
+
+ private final DecodingState AFTER_SKIP_ENTITY_HEADER = new CRLFDecodingState() {
+ @Override
+ protected DecodingState finishDecode(boolean foundCRLF,
+ ProtocolDecoderOutput out) throws Exception {
+ return FIND_END_OF_TRAILER;
+ }
+ };
}
Modified: mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/HttpDecoderException.java
URL: http://svn.apache.org/viewvc/mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/HttpDecoderException.java?rev=592337&r1=592336&r2=592337&view=diff
==============================================================================
--- mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/HttpDecoderException.java (original)
+++ mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/HttpDecoderException.java Tue Nov 6 00:59:36 2007
@@ -22,48 +22,48 @@
import org.apache.mina.filter.codec.ProtocolDecoderException;
import org.safehaus.asyncweb.common.HttpResponseStatus;
-
/**
* An exception thrown by HTTP decoders.
- *
+ *
* This exception enables decoders which are capable of determining the type of
* failure to specify the response which is ultimately returned to the client.
- *
+ *
* @author irvingd
* @author trustin
* @version $Rev$, $Date$
*/
public class HttpDecoderException extends ProtocolDecoderException {
- private static final long serialVersionUID = 3256999969109063480L;
-
- private HttpResponseStatus responseStatus;
-
- /**
- * Creates a new instance with the default response status code
- * ({@link HttpResponseStatus#BAD_REQUEST}).
- *
- * @param message The description of the failure
- */
- public HttpDecoderException(String message) {
- this(message, HttpResponseStatus.BAD_REQUEST);
- }
-
- /**
- * Creates a new instance.
- *
- * @param message A description of the failure
- * @param responseStatus The associated response status
- */
- public HttpDecoderException(String message, HttpResponseStatus responseStatus) {
- super(message);
- this.responseStatus = responseStatus;
- }
-
- /**
- * Returns the response status associated with this exception.
- */
- public HttpResponseStatus getResponseStatus() {
- return responseStatus;
- }
+ private static final long serialVersionUID = 3256999969109063480L;
+
+ private HttpResponseStatus responseStatus;
+
+ /**
+ * Creates a new instance with the default response status code
+ * ({@link HttpResponseStatus#BAD_REQUEST}).
+ *
+ * @param message The description of the failure
+ */
+ public HttpDecoderException(String message) {
+ this(message, HttpResponseStatus.BAD_REQUEST);
+ }
+
+ /**
+ * Creates a new instance.
+ *
+ * @param message A description of the failure
+ * @param responseStatus The associated response status
+ */
+ public HttpDecoderException(String message,
+ HttpResponseStatus responseStatus) {
+ super(message);
+ this.responseStatus = responseStatus;
+ }
+
+ /**
+ * Returns the response status associated with this exception.
+ */
+ public HttpResponseStatus getResponseStatus() {
+ return responseStatus;
+ }
}
Modified: mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/HttpHeaderDecodingState.java
URL: http://svn.apache.org/viewvc/mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/HttpHeaderDecodingState.java?rev=592337&r1=592336&r2=592337&view=diff
==============================================================================
--- mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/HttpHeaderDecodingState.java (original)
+++ mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/HttpHeaderDecodingState.java Tue Nov 6 00:59:36 2007
@@ -38,94 +38,101 @@
* Decodes the Headers of HTTP requests.
* <code>HttpHeaderDecoder</code> employs several sub-decoders - each taking
* the responsibility of decoding a specific part of the header.<br/>
- *
+ *
* @author irvingd
* @author trustin
* @version $Rev$, $Date$
*/
abstract class HttpHeaderDecodingState extends DecodingStateMachine {
- private static final Charset US_ASCII = Charset.forName("US-ASCII");
- private static final Charset UTF_8 = Charset.forName("UTF-8");
-
- private final CharsetDecoder asciiDecoder = US_ASCII.newDecoder();
- private final CharsetDecoder utf8Decoder = UTF_8.newDecoder();
-
- private Map<String, List<String>> headers = new HashMap<String, List<String>>();
-
- private String lastHeaderName;
- private StringBuilder lastHeaderValue;
-
- HttpHeaderDecodingState() {
- //cookieParser = new CookieParser();
- }
-
- @Override
- protected DecodingState init() throws Exception {
- return FIND_EMPTY_LINE;
- }
-
- @Override
- protected void destroy() throws Exception {
- }
+ private static final Charset US_ASCII = Charset.forName("US-ASCII");
- private final DecodingState FIND_EMPTY_LINE = new CRLFDecodingState() {
- @Override
- protected DecodingState finishDecode(boolean foundCRLF, ProtocolDecoderOutput out) throws Exception {
- if (foundCRLF) {
- out.write(headers);
- // Reset the state.
- headers = new HashMap<String, List<String>>();
- return null;
- } else {
- return READ_HEADER_NAME;
- }
- }
- };
-
- private final DecodingState READ_HEADER_NAME = new ConsumeToTerminatorDecodingState((byte) ':') {
- @Override
- protected DecodingState finishDecode(IoBuffer product, ProtocolDecoderOutput out) throws Exception {
- lastHeaderName = product.getString(asciiDecoder);
- return AFTER_READ_HEADER_NAME;
+ private static final Charset UTF_8 = Charset.forName("UTF-8");
+
+ private final CharsetDecoder asciiDecoder = US_ASCII.newDecoder();
+
+ private final CharsetDecoder utf8Decoder = UTF_8.newDecoder();
+
+ private Map<String, List<String>> headers = new HashMap<String, List<String>>();
+
+ private String lastHeaderName;
+
+ private StringBuilder lastHeaderValue;
+
+ HttpHeaderDecodingState() {
+ //cookieParser = new CookieParser();
}
- };
-
- private final DecodingState AFTER_READ_HEADER_NAME = new LinearWhitespaceSkippingState() {
+
@Override
- protected DecodingState finishDecode(int skippedBytes) throws Exception {
- lastHeaderValue = new StringBuilder();
- return READ_HEADER_VALUE;
+ protected DecodingState init() throws Exception {
+ return FIND_EMPTY_LINE;
}
- };
-
- private final DecodingState READ_HEADER_VALUE = new ConsumeToCRLFDecodingState() {
+
@Override
- protected DecodingState finishDecode(IoBuffer product, ProtocolDecoderOutput out) throws Exception {
- String value = product.getString(utf8Decoder);
- if (lastHeaderValue.length() == 0) {
- lastHeaderValue.append(value);
- } else {
- lastHeaderValue.append(' ');
- lastHeaderValue.append(value);
- }
- return AFTER_READ_HEADER_VALUE;
+ protected void destroy() throws Exception {
}
- };
-
- private final DecodingState AFTER_READ_HEADER_VALUE = new LinearWhitespaceSkippingState() {
- @Override
- protected DecodingState finishDecode(int skippedBytes) throws Exception {
- if (skippedBytes == 0) {
- List<String> values = headers.get(lastHeaderName);
- if (values == null) {
- values = new ArrayList<String>();
- headers.put(lastHeaderName, values);
+
+ private final DecodingState FIND_EMPTY_LINE = new CRLFDecodingState() {
+ @Override
+ protected DecodingState finishDecode(boolean foundCRLF,
+ ProtocolDecoderOutput out) throws Exception {
+ if (foundCRLF) {
+ out.write(headers);
+ // Reset the state.
+ headers = new HashMap<String, List<String>>();
+ return null;
+ } else {
+ return READ_HEADER_NAME;
+ }
}
- values.add(lastHeaderValue.toString());
- return FIND_EMPTY_LINE;
- } else {
- return READ_HEADER_VALUE;
- }
- }
- };
+ };
+
+ private final DecodingState READ_HEADER_NAME = new ConsumeToTerminatorDecodingState(
+ (byte) ':') {
+ @Override
+ protected DecodingState finishDecode(IoBuffer product,
+ ProtocolDecoderOutput out) throws Exception {
+ lastHeaderName = product.getString(asciiDecoder);
+ return AFTER_READ_HEADER_NAME;
+ }
+ };
+
+ private final DecodingState AFTER_READ_HEADER_NAME = new LinearWhitespaceSkippingState() {
+ @Override
+ protected DecodingState finishDecode(int skippedBytes) throws Exception {
+ lastHeaderValue = new StringBuilder();
+ return READ_HEADER_VALUE;
+ }
+ };
+
+ private final DecodingState READ_HEADER_VALUE = new ConsumeToCRLFDecodingState() {
+ @Override
+ protected DecodingState finishDecode(IoBuffer product,
+ ProtocolDecoderOutput out) throws Exception {
+ String value = product.getString(utf8Decoder);
+ if (lastHeaderValue.length() == 0) {
+ lastHeaderValue.append(value);
+ } else {
+ lastHeaderValue.append(' ');
+ lastHeaderValue.append(value);
+ }
+ return AFTER_READ_HEADER_VALUE;
+ }
+ };
+
+ private final DecodingState AFTER_READ_HEADER_VALUE = new LinearWhitespaceSkippingState() {
+ @Override
+ protected DecodingState finishDecode(int skippedBytes) throws Exception {
+ if (skippedBytes == 0) {
+ List<String> values = headers.get(lastHeaderName);
+ if (values == null) {
+ values = new ArrayList<String>();
+ headers.put(lastHeaderName, values);
+ }
+ values.add(lastHeaderValue.toString());
+ return FIND_EMPTY_LINE;
+ } else {
+ return READ_HEADER_VALUE;
+ }
+ }
+ };
}
Modified: mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/HttpRequestDecodingState.java
URL: http://svn.apache.org/viewvc/mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/HttpRequestDecodingState.java?rev=592337&r1=592336&r2=592337&view=diff
==============================================================================
--- mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/HttpRequestDecodingState.java (original)
+++ mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/HttpRequestDecodingState.java Tue Nov 6 00:59:36 2007
@@ -40,231 +40,247 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
/**
* Parses HTTP requests.
* Clients should register a <code>HttpRequestParserListener</code>
* in order to receive notifications at important stages of request
* building.<br/>
- *
+ *
* <code>HttpRequestParser</code>s should not be built for each request
* as each parser constructs an underlying state machine which is
* relatively costly to build.<br/> Instead, parsers should be pooled.<br/>
- *
+ *
* Note, however, that a parser <i>must</i> be <code>prepare</code>d before
* each new parse.
- *
+ *
* @author irvingd
* @author trustin
* @version $Rev$, $Date$
*/
public abstract class HttpRequestDecodingState extends DecodingStateMachine {
- private static final Logger LOG = LoggerFactory.getLogger(HttpRequestDecodingState.class);
- private static final String HEADER_COOKIE = "Cookie";
-
- /**
- * The header which provides a requests transfer coding
- */
- private static final String TRANSFER_CODING = "transfer-encoding";
-
- /**
- * The chunked coding
- */
- private static final String CHUNKED = "chunked";
-
- /**
- * The header which provides a requests content length
- */
- private static final String CONTENT_LENGTH = "content-length";
-
- /**
- * Indicates the start of a coding extension
- */
- private static final char EXTENSION_CHAR = ';';
-
- /**
- * The request we are building
- */
- private MutableHttpRequest request;
- private boolean parseCookies = true;
-
- public HttpRequestDecodingState() {
- }
-
- public boolean isParseCookies() {
- return parseCookies;
- }
-
- public void setParseCookies(boolean parseCookies) {
- this.parseCookies = parseCookies;
- }
-
- @Override
- protected DecodingState init() throws Exception {
- request = new DefaultHttpRequest();
- return SKIP_EMPTY_LINES;
- }
-
- @Override
- protected void destroy() throws Exception {
- }
-
- private final DecodingState SKIP_EMPTY_LINES = new CRLFDecodingState() {
+ private static final Logger LOG = LoggerFactory
+ .getLogger(HttpRequestDecodingState.class);
- @Override
- protected DecodingState finishDecode(boolean foundCRLF, ProtocolDecoderOutput out) throws Exception {
- if (foundCRLF) {
- return this;
- } else {
- return READ_REQUEST_LINE;
- }
+ private static final String HEADER_COOKIE = "Cookie";
+
+ /**
+ * The header which provides a requests transfer coding
+ */
+ private static final String TRANSFER_CODING = "transfer-encoding";
+
+ /**
+ * The chunked coding
+ */
+ private static final String CHUNKED = "chunked";
+
+ /**
+ * The header which provides a requests content length
+ */
+ private static final String CONTENT_LENGTH = "content-length";
+
+ /**
+ * Indicates the start of a coding extension
+ */
+ private static final char EXTENSION_CHAR = ';';
+
+ /**
+ * The request we are building
+ */
+ private MutableHttpRequest request;
+
+ private boolean parseCookies = true;
+
+ public HttpRequestDecodingState() {
}
- };
-
- private final DecodingState READ_REQUEST_LINE = new HttpRequestLineDecodingState() {
+
+ public boolean isParseCookies() {
+ return parseCookies;
+ }
+
+ public void setParseCookies(boolean parseCookies) {
+ this.parseCookies = parseCookies;
+ }
+
@Override
- protected DecodingState finishDecode(List<Object> childProducts, ProtocolDecoderOutput out) throws Exception {
- URI requestUri = (URI) childProducts.get(1);
- request.setMethod((HttpMethod) childProducts.get(0));
- request.setRequestUri(requestUri);
- request.setProtocolVersion((HttpVersion) childProducts.get(2));
- request.setParameters(requestUri.getQuery());
- return READ_HEADERS;
+ protected DecodingState init() throws Exception {
+ request = new DefaultHttpRequest();
+ return SKIP_EMPTY_LINES;
}
- };
-
- private final DecodingState READ_HEADERS = new HttpHeaderDecodingState() {
+
@Override
- @SuppressWarnings("unchecked")
- protected DecodingState finishDecode(List<Object> childProducts, ProtocolDecoderOutput out) throws Exception {
- Map<String, List<String>> headers = (Map<String, List<String>>) childProducts.get(0);
- if (parseCookies) {
- List<String> cookies = headers.remove(HEADER_COOKIE);
- if (cookies != null && !cookies.isEmpty()) {
- if (cookies.size() > 1) {
- if (LOG.isWarnEnabled()) {
- LOG.warn("Ignoring extra cookie headers: " + cookies.subList(1, cookies.size()));
+ protected void destroy() throws Exception {
+ }
+
+ private final DecodingState SKIP_EMPTY_LINES = new CRLFDecodingState() {
+
+ @Override
+ protected DecodingState finishDecode(boolean foundCRLF,
+ ProtocolDecoderOutput out) throws Exception {
+ if (foundCRLF) {
+ return this;
+ } else {
+ return READ_REQUEST_LINE;
}
- }
- request.setCookies(cookies.get(0));
}
- }
- request.setHeaders(headers);
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("Decoded header: " + request.getHeaders());
- }
-
- // Select appropriate body decoding state.
- boolean isChunked = false;
- if (request.getProtocolVersion() == HttpVersion.HTTP_1_1) {
- LOG.debug("Request is HTTP 1/1. Checking for transfer coding");
- isChunked = isChunked(request);
- }
- else {
- LOG.debug("Request is not HTTP 1/1. Using content length");
- }
- DecodingState nextState;
- if (isChunked) {
- LOG.debug("Using chunked decoder for request");
- nextState = new ChunkedBodyDecodingState() {
- @Override
- protected DecodingState finishDecode(List<Object> childProducts, ProtocolDecoderOutput out) throws Exception {
- if (childProducts.size() != 1) {
- int chunkSize = 0;
- for (Object product: childProducts) {
- IoBuffer chunk = (IoBuffer) product;
- chunkSize += chunk.remaining();
- }
-
- IoBuffer body = IoBuffer.allocate(chunkSize);
- for (Object product: childProducts) {
- IoBuffer chunk = (IoBuffer) product;
- body.put(chunk);
- }
- body.flip();
- request.setContent(new ByteBufferContent(body));
+ };
+
+ private final DecodingState READ_REQUEST_LINE = new HttpRequestLineDecodingState() {
+ @Override
+ protected DecodingState finishDecode(List<Object> childProducts,
+ ProtocolDecoderOutput out) throws Exception {
+ URI requestUri = (URI) childProducts.get(1);
+ request.setMethod((HttpMethod) childProducts.get(0));
+ request.setRequestUri(requestUri);
+ request.setProtocolVersion((HttpVersion) childProducts.get(2));
+ request.setParameters(requestUri.getQuery());
+ return READ_HEADERS;
+ }
+ };
+
+ private final DecodingState READ_HEADERS = new HttpHeaderDecodingState() {
+ @Override
+ @SuppressWarnings("unchecked")
+ protected DecodingState finishDecode(List<Object> childProducts,
+ ProtocolDecoderOutput out) throws Exception {
+ Map<String, List<String>> headers = (Map<String, List<String>>) childProducts
+ .get(0);
+ if (parseCookies) {
+ List<String> cookies = headers.remove(HEADER_COOKIE);
+ if (cookies != null && !cookies.isEmpty()) {
+ if (cookies.size() > 1) {
+ if (LOG.isWarnEnabled()) {
+ LOG.warn("Ignoring extra cookie headers: "
+ + cookies.subList(1, cookies.size()));
+ }
+ }
+ request.setCookies(cookies.get(0));
+ }
+ }
+ request.setHeaders(headers);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Decoded header: " + request.getHeaders());
+ }
+
+ // Select appropriate body decoding state.
+ boolean isChunked = false;
+ if (request.getProtocolVersion() == HttpVersion.HTTP_1_1) {
+ LOG.debug("Request is HTTP 1/1. Checking for transfer coding");
+ isChunked = isChunked(request);
} else {
- request.setContent(new ByteBufferContent((IoBuffer) childProducts.get(0)));
+ LOG.debug("Request is not HTTP 1/1. Using content length");
}
-
- out.write(request);
- return null;
- }
- };
- } else {
- int length = getContentLength(request);
- if (length > 0) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("Using fixed length decoder for request with length " + length);
- }
- nextState = new FixedLengthDecodingState(length) {
- @Override
- protected DecodingState finishDecode(IoBuffer readData, ProtocolDecoderOutput out) throws Exception {
- request.setContent(new ByteBufferContent(readData));
- out.write(request);
- return null;
- }
- };
- } else {
- LOG.debug("No entity body for this request");
- out.write(request);
- nextState = null;
- }
- }
- return nextState;
- }
-
- /**
- * Obtains the content length from the specified request
- *
- * @param request The request
- * @return The content length, or 0 if not specified
- * @throws HttpDecoderException If an invalid content length is specified
- */
- private int getContentLength(HttpRequest request) throws ProtocolDecoderException {
- int length = 0;
- String lengthValue = request.getHeader(CONTENT_LENGTH);
- if (lengthValue != null) {
- try {
- length = Integer.parseInt(lengthValue);
- } catch (NumberFormatException e) {
- HttpCodecUtils.throwDecoderException("Invalid content length: " + length,
- HttpResponseStatus.BAD_REQUEST);
+ DecodingState nextState;
+ if (isChunked) {
+ LOG.debug("Using chunked decoder for request");
+ nextState = new ChunkedBodyDecodingState() {
+ @Override
+ protected DecodingState finishDecode(
+ List<Object> childProducts,
+ ProtocolDecoderOutput out) throws Exception {
+ if (childProducts.size() != 1) {
+ int chunkSize = 0;
+ for (Object product : childProducts) {
+ IoBuffer chunk = (IoBuffer) product;
+ chunkSize += chunk.remaining();
+ }
+
+ IoBuffer body = IoBuffer.allocate(chunkSize);
+ for (Object product : childProducts) {
+ IoBuffer chunk = (IoBuffer) product;
+ body.put(chunk);
+ }
+ body.flip();
+ request.setContent(new ByteBufferContent(body));
+ } else {
+ request.setContent(new ByteBufferContent(
+ (IoBuffer) childProducts.get(0)));
+ }
+
+ out.write(request);
+ return null;
+ }
+ };
+ } else {
+ int length = getContentLength(request);
+ if (length > 0) {
+ if (LOG.isDebugEnabled()) {
+ LOG
+ .debug("Using fixed length decoder for request with length "
+ + length);
+ }
+ nextState = new FixedLengthDecodingState(length) {
+ @Override
+ protected DecodingState finishDecode(IoBuffer readData,
+ ProtocolDecoderOutput out) throws Exception {
+ request.setContent(new ByteBufferContent(readData));
+ out.write(request);
+ return null;
+ }
+ };
+ } else {
+ LOG.debug("No entity body for this request");
+ out.write(request);
+ nextState = null;
+ }
+ }
+ return nextState;
}
- }
- return length;
- }
-
- /**
- * Determines whether a specified request employs a chunked
- * transfer coding
- *
- * @param request The request
- * @return <code>true</code> iff the request employs a
- * chunked transfer coding
- * @throws HttpDecoderException
- * If the request employs an unsupported coding
- */
- private boolean isChunked(HttpRequest request) throws ProtocolDecoderException {
- boolean isChunked = false;
- String coding = request.getHeader(TRANSFER_CODING);
- if (coding != null) {
- int extensionIndex = coding.indexOf(EXTENSION_CHAR);
- if (extensionIndex != -1) {
- coding = coding.substring(0, extensionIndex);
+
+ /**
+ * Obtains the content length from the specified request
+ *
+ * @param request The request
+ * @return The content length, or 0 if not specified
+ * @throws HttpDecoderException If an invalid content length is specified
+ */
+ private int getContentLength(HttpRequest request)
+ throws ProtocolDecoderException {
+ int length = 0;
+ String lengthValue = request.getHeader(CONTENT_LENGTH);
+ if (lengthValue != null) {
+ try {
+ length = Integer.parseInt(lengthValue);
+ } catch (NumberFormatException e) {
+ HttpCodecUtils.throwDecoderException(
+ "Invalid content length: " + length,
+ HttpResponseStatus.BAD_REQUEST);
+ }
+ }
+ return length;
}
- if (CHUNKED.equalsIgnoreCase(coding)) {
- isChunked = true;
- } else {
- // As we only support chunked encoding, any other encoding
- // is unsupported
- HttpCodecUtils.throwDecoderException("Unknown transfer coding " + coding,
- HttpResponseStatus.NOT_IMPLEMENTED);
+
+ /**
+ * Determines whether a specified request employs a chunked
+ * transfer coding
+ *
+ * @param request The request
+ * @return <code>true</code> iff the request employs a
+ * chunked transfer coding
+ * @throws HttpDecoderException
+ * If the request employs an unsupported coding
+ */
+ private boolean isChunked(HttpRequest request)
+ throws ProtocolDecoderException {
+ boolean isChunked = false;
+ String coding = request.getHeader(TRANSFER_CODING);
+ if (coding != null) {
+ int extensionIndex = coding.indexOf(EXTENSION_CHAR);
+ if (extensionIndex != -1) {
+ coding = coding.substring(0, extensionIndex);
+ }
+ if (CHUNKED.equalsIgnoreCase(coding)) {
+ isChunked = true;
+ } else {
+ // As we only support chunked encoding, any other encoding
+ // is unsupported
+ HttpCodecUtils.throwDecoderException(
+ "Unknown transfer coding " + coding,
+ HttpResponseStatus.NOT_IMPLEMENTED);
+ }
+ }
+ return isChunked;
}
- }
- return isChunked;
- }
- };
+ };
}
Modified: mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/HttpRequestLineDecodingState.java
URL: http://svn.apache.org/viewvc/mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/HttpRequestLineDecodingState.java?rev=592337&r1=592336&r2=592337&view=diff
==============================================================================
--- mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/HttpRequestLineDecodingState.java (original)
+++ mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/HttpRequestLineDecodingState.java Tue Nov 6 00:59:36 2007
@@ -32,8 +32,8 @@
import org.safehaus.asyncweb.codec.decoder.support.DecodingStateMachine;
import org.safehaus.asyncweb.codec.decoder.support.LinearWhitespaceSkippingState;
import org.safehaus.asyncweb.common.HttpMethod;
-import org.safehaus.asyncweb.common.HttpVersion;
import org.safehaus.asyncweb.common.HttpResponseStatus;
+import org.safehaus.asyncweb.common.HttpVersion;
/**
* Decodes an HTTP request line - populating an associated <code>Request</code>
@@ -41,99 +41,108 @@
* <pre>
* Request-Line = Method SP Request-URI SP HTTP-Version CRLF
* </pre>
- *
+ *
* @author irvingd
*
*/
abstract class HttpRequestLineDecodingState extends DecodingStateMachine {
- private static final Charset US_ASCII = Charset.forName("US-ASCII");
- private static final Charset UTF_8 = Charset.forName("UTF-8");
-
- private final CharsetDecoder asciiDecoder = US_ASCII.newDecoder();
- private final CharsetDecoder utf8Decoder = UTF_8.newDecoder();
-
- @Override
- protected DecodingState init() throws Exception {
- return READ_METHOD;
- }
-
- @Override
- protected void destroy() throws Exception {
- }
-
- private final DecodingState READ_METHOD = new ConsumeToLinearWhitespaceDecodingState() {
- @Override
- protected DecodingState finishDecode(IoBuffer product, ProtocolDecoderOutput out) throws Exception {
- HttpMethod method = HttpMethod.valueOf(product.getString(asciiDecoder));
+ private static final Charset US_ASCII = Charset.forName("US-ASCII");
- if (method == null) {
- HttpCodecUtils.throwDecoderException("Bad method",
- HttpResponseStatus.NOT_IMPLEMENTED);
- }
-
- out.write(method);
+ private static final Charset UTF_8 = Charset.forName("UTF-8");
- return AFTER_READ_METHOD;
- }
- };
-
- private final DecodingState AFTER_READ_METHOD = new LinearWhitespaceSkippingState() {
- @Override
- protected DecodingState finishDecode(int skippedBytes) throws Exception {
- return READ_REQUEST_URI;
- }
- };
-
- private final DecodingState READ_REQUEST_URI = new ConsumeToLinearWhitespaceDecodingState() {
- @Override
- protected DecodingState finishDecode(IoBuffer product, ProtocolDecoderOutput out) throws Exception {
- out.write(new URI(product.getString(utf8Decoder)));
- return AFTER_READ_REQUEST_URI;
- }
- };
-
- private final DecodingState AFTER_READ_REQUEST_URI = new LinearWhitespaceSkippingState() {
- @Override
- protected DecodingState finishDecode(int skippedBytes) throws Exception {
- return READ_PROTOCOL_VERSION;
- }
- };
-
- private final DecodingState READ_PROTOCOL_VERSION = new ConsumeToDynamicTerminatorDecodingState() {
- @Override
- protected DecodingState finishDecode(IoBuffer product, ProtocolDecoderOutput out) throws Exception {
- String versionStr = product.getString(asciiDecoder);
- HttpVersion version = HttpVersion.valueOf(versionStr);
- if (version == null) {
- HttpCodecUtils.throwDecoderException("Unsupported HTTP version: " + versionStr ,
- HttpResponseStatus.HTTP_VERSION_NOT_SUPPORTED);
- }
- out.write(version);
- return AFTER_READ_PROTOCOL_VERSION;
- }
+ private final CharsetDecoder asciiDecoder = US_ASCII.newDecoder();
- @Override
- protected boolean isTerminator(byte b) {
- return (Character.isWhitespace(b));
- }
- };
+ private final CharsetDecoder utf8Decoder = UTF_8.newDecoder();
- private final DecodingState AFTER_READ_PROTOCOL_VERSION = new LinearWhitespaceSkippingState() {
- @Override
- protected DecodingState finishDecode(int skippedBytes) throws Exception {
- return FINISH;
- }
- };
-
- private final DecodingState FINISH = new CRLFDecodingState() {
@Override
- protected DecodingState finishDecode(boolean foundCRLF, ProtocolDecoderOutput out) throws Exception {
- if (!foundCRLF) {
- HttpCodecUtils.throwDecoderException("Expected CR/LF at the end of the request line.");
- }
-
- return null;
- }
- };
+ protected DecodingState init() throws Exception {
+ return READ_METHOD;
+ }
+
+ @Override
+ protected void destroy() throws Exception {
+ }
+
+ private final DecodingState READ_METHOD = new ConsumeToLinearWhitespaceDecodingState() {
+ @Override
+ protected DecodingState finishDecode(IoBuffer product,
+ ProtocolDecoderOutput out) throws Exception {
+ HttpMethod method = HttpMethod.valueOf(product
+ .getString(asciiDecoder));
+
+ if (method == null) {
+ HttpCodecUtils.throwDecoderException("Bad method",
+ HttpResponseStatus.NOT_IMPLEMENTED);
+ }
+
+ out.write(method);
+
+ return AFTER_READ_METHOD;
+ }
+ };
+
+ private final DecodingState AFTER_READ_METHOD = new LinearWhitespaceSkippingState() {
+ @Override
+ protected DecodingState finishDecode(int skippedBytes) throws Exception {
+ return READ_REQUEST_URI;
+ }
+ };
+
+ private final DecodingState READ_REQUEST_URI = new ConsumeToLinearWhitespaceDecodingState() {
+ @Override
+ protected DecodingState finishDecode(IoBuffer product,
+ ProtocolDecoderOutput out) throws Exception {
+ out.write(new URI(product.getString(utf8Decoder)));
+ return AFTER_READ_REQUEST_URI;
+ }
+ };
+
+ private final DecodingState AFTER_READ_REQUEST_URI = new LinearWhitespaceSkippingState() {
+ @Override
+ protected DecodingState finishDecode(int skippedBytes) throws Exception {
+ return READ_PROTOCOL_VERSION;
+ }
+ };
+
+ private final DecodingState READ_PROTOCOL_VERSION = new ConsumeToDynamicTerminatorDecodingState() {
+ @Override
+ protected DecodingState finishDecode(IoBuffer product,
+ ProtocolDecoderOutput out) throws Exception {
+ String versionStr = product.getString(asciiDecoder);
+ HttpVersion version = HttpVersion.valueOf(versionStr);
+ if (version == null) {
+ HttpCodecUtils.throwDecoderException(
+ "Unsupported HTTP version: " + versionStr,
+ HttpResponseStatus.HTTP_VERSION_NOT_SUPPORTED);
+ }
+ out.write(version);
+ return AFTER_READ_PROTOCOL_VERSION;
+ }
+
+ @Override
+ protected boolean isTerminator(byte b) {
+ return Character.isWhitespace(b);
+ }
+ };
+
+ private final DecodingState AFTER_READ_PROTOCOL_VERSION = new LinearWhitespaceSkippingState() {
+ @Override
+ protected DecodingState finishDecode(int skippedBytes) throws Exception {
+ return FINISH;
+ }
+ };
+
+ private final DecodingState FINISH = new CRLFDecodingState() {
+ @Override
+ protected DecodingState finishDecode(boolean foundCRLF,
+ ProtocolDecoderOutput out) throws Exception {
+ if (!foundCRLF) {
+ HttpCodecUtils
+ .throwDecoderException("Expected CR/LF at the end of the request line.");
+ }
+
+ return null;
+ }
+ };
}
Modified: mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/support/ConsumeToCRLFDecodingState.java
URL: http://svn.apache.org/viewvc/mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/support/ConsumeToCRLFDecodingState.java?rev=592337&r1=592336&r2=592337&view=diff
==============================================================================
--- mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/support/ConsumeToCRLFDecodingState.java (original)
+++ mina/sandbox/asyncweb/core/src/main/java/org/safehaus/asyncweb/codec/decoder/support/ConsumeToCRLFDecodingState.java Tue Nov 6 00:59:36 2007
@@ -22,94 +22,95 @@
import org.apache.mina.common.IoBuffer;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
-
/**
* A decoder which writes all read bytes in to a known <code>Bytes</code>
* context until a <code>CRLF</code> has been encountered
*/
public abstract class ConsumeToCRLFDecodingState implements DecodingState {
- /**
- * Carriage return character
- */
- private static final byte CR = 13;
-
- /**
- * Line feed character
- */
- private static final byte LF = 10;
-
- private boolean lastIsCR;
- private IoBuffer buffer;
-
-
- /**
- * Creates a new instance.
- */
- public ConsumeToCRLFDecodingState() {
- }
-
- public DecodingState decode(IoBuffer in, ProtocolDecoderOutput out) throws Exception {
- int beginPos = in.position();
- int limit = in.limit();
- int terminatorPos = -1;
-
- for (int i = beginPos; i < limit; i++) {
- byte b = in.get(i);
- if (b == CR) {
- lastIsCR = true;
- } else {
- if (b == LF && lastIsCR) {
- terminatorPos = i;
- break;
- }
- lastIsCR = false;
- }
+ /**
+ * Carriage return character
+ */
+ private static final byte CR = 13;
+
+ /**
+ * Line feed character
+ */
+ private static final byte LF = 10;
+
+ private boolean lastIsCR;
+
+ private IoBuffer buffer;
+
+ /**
+ * Creates a new instance.
+ */
+ public ConsumeToCRLFDecodingState() {
}
-
- if (terminatorPos >= 0) {
- IoBuffer product;
-
- int endPos = terminatorPos - 1;
-
- if (beginPos < endPos) {
- in.limit(endPos);
-
- if (buffer == null) {
- product = in.slice();
- } else {
- buffer.put(in);
- product = buffer.flip();
- buffer = null;
+
+ public DecodingState decode(IoBuffer in, ProtocolDecoderOutput out)
+ throws Exception {
+ int beginPos = in.position();
+ int limit = in.limit();
+ int terminatorPos = -1;
+
+ for (int i = beginPos; i < limit; i++) {
+ byte b = in.get(i);
+ if (b == CR) {
+ lastIsCR = true;
+ } else {
+ if (b == LF && lastIsCR) {
+ terminatorPos = i;
+ break;
+ }
+ lastIsCR = false;
+ }
}
-
- in.limit(limit);
- } else {
- // When input contained only CR or LF rather than actual data...
- if (buffer == null) {
- product = IoBuffer.allocate(1);
- product.limit(0);
+
+ if (terminatorPos >= 0) {
+ IoBuffer product;
+
+ int endPos = terminatorPos - 1;
+
+ if (beginPos < endPos) {
+ in.limit(endPos);
+
+ if (buffer == null) {
+ product = in.slice();
+ } else {
+ buffer.put(in);
+ product = buffer.flip();
+ buffer = null;
+ }
+
+ in.limit(limit);
+ } else {
+ // When input contained only CR or LF rather than actual data...
+ if (buffer == null) {
+ product = IoBuffer.allocate(1);
+ product.limit(0);
+ } else {
+ product = buffer.flip();
+ buffer = null;
+ }
+ }
+ in.position(terminatorPos + 1);
+ return finishDecode(product, out);
} else {
- product = buffer.flip();
- buffer = null;
+ in.position(beginPos);
+ if (buffer == null) {
+ buffer = IoBuffer.allocate(in.remaining());
+ buffer.setAutoExpand(true);
+ }
+
+ buffer.put(in);
+ if (lastIsCR) {
+ buffer.position(buffer.position() - 1);
+ }
+ return this;
}
- }
- in.position(terminatorPos + 1);
- return finishDecode(product, out);
- } else {
- in.position(beginPos);
- if (buffer == null) {
- buffer = IoBuffer.allocate(in.remaining());
- buffer.setAutoExpand(true);
- }
-
- buffer.put(in);
- if (lastIsCR) {
- buffer.position(buffer.position() - 1);
- }
- return this;
}
- }
- protected abstract DecodingState finishDecode(IoBuffer product, ProtocolDecoderOutput out) throws Exception;
+ protected abstract DecodingState finishDecode(IoBuffer product,
+ ProtocolDecoderOutput out) throws Exception;
}