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;
 }