geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jgenen...@apache.org
Subject svn commit: r568787 - in /geronimo/sandbox/AsyncHttpClient/src: main/java/org/apache/ahc/codec/ test/java/org/apache/ahc/
Date Thu, 23 Aug 2007 00:55:35 GMT
Author: jgenender
Date: Wed Aug 22 17:55:34 2007
New Revision: 568787

URL: http://svn.apache.org/viewvc?rev=568787&view=rev
Log:
Add 100 continue handling and chunking

Added:
    geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/ChunkedTest.java
    geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/FakeIoSession.java
    geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/FakeProtocolDecoderOutput.java
Modified:
    geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpDecoder.java
    geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpMessage.java
    geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpResponseDecoder.java
    geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpResponseMessage.java

Modified: geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpDecoder.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpDecoder.java?rev=568787&r1=568786&r2=568787&view=diff
==============================================================================
--- geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpDecoder.java (original)
+++ geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpDecoder.java Wed
Aug 22 17:55:34 2007
@@ -120,15 +120,44 @@
         }
 
         if (name.equalsIgnoreCase(TRANSFER_ENCODING) && value != null &&
value.equalsIgnoreCase(CHUNKED)) {
-            msg.chunked = true;
+            msg.setChunked(true);
         }
 
     }
 
-    public void decodeContent(ByteBuffer in, HttpResponseMessage msg){
+    public int decodeSize(String line) throws Exception {
+        String strippedLine = line.trim().toLowerCase();
+        for (int i = 0; i < strippedLine.length(); i++) {
+            char ch = strippedLine.charAt(i);
+            //Once we hit a non-numeric character, parse the number we have
+            if ((ch < '0' || (ch > '9' && ch < 'a') || ch > 'f')) {
+                return Integer.parseInt(strippedLine.substring(0, i), 16);
+            }
+        }
+
+        //We got here, so the entire line passes
+        return Integer.parseInt(strippedLine, 16);
+    }
+
+    public void decodeContent(ByteBuffer in, HttpResponseMessage msg) throws Exception{
         byte content[] = new byte[msg.getContentLength()];
         in.get(content);
-        msg.setContent(content);
+        msg.addContent(content);
+    }
+
+    public void decodeChunkedContent(ByteBuffer in, HttpResponseMessage msg) throws Exception
{
+        int toRead = msg.getExpectedToRead();
+        if ((in.get(in.position() + toRead) != CR) && (in.get(in.position() + toRead
+ 1)!= LF)) {
+            throw new IOException("Invalid HTTP response - chunk does not end with CRLF");
+
+        }
+        byte content[] = new byte[toRead];
+        in.get(content);
+        msg.addContent(content);
+
+        //Pop the CRLF
+        in.get();
+        in.get();
     }
 
     public Cookie decodeCookie(String cookieStr) throws Exception {

Modified: geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpMessage.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpMessage.java?rev=568787&r1=568786&r2=568787&view=diff
==============================================================================
--- geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpMessage.java (original)
+++ geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpMessage.java Wed
Aug 22 17:55:34 2007
@@ -21,13 +21,13 @@
 
 import org.apache.ahc.util.NameValuePair;
 
-import java.util.HashMap;
-import java.util.Map;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
 public class HttpMessage {
-    
+
     public final static String CONTENT_TYPE = "Content-Type";
     public final static String CONTENT_LENGTH = "Content-Length";
 
@@ -35,21 +35,27 @@
     protected List<Cookie> cookies = new ArrayList<Cookie>();
     protected String contentType;
     protected int contentLength;
-    protected byte[] content = null;
+    protected ByteArrayOutputStream content;
 
-    public String getStringContent(){
+    public String getStringContent() {
         if (content == null)
             return null;
 
-        return new String(content);
+        return new String(content.toByteArray());
     }
 
     public byte[] getContent() {
-        return content;
+        if (content == null)
+            return null;
+
+        return content.toByteArray();
     }
 
-    public void setContent(byte[] content) {
-        this.content = content;
+    public void addContent(byte[] content) throws IOException {
+        if (this.content == null)
+            this.content = new ByteArrayOutputStream();
+
+        this.content.write(content);
     }
 
     public List<Cookie> getCookies() {
@@ -60,7 +66,7 @@
         this.cookies = cookies;
     }
 
-    public void addCookie(Cookie cookie){
+    public void addCookie(Cookie cookie) {
         this.cookies.add(cookie);
     }
 
@@ -73,12 +79,12 @@
         this.headers = headers;
     }
 
-    public void addHeader(NameValuePair header){
+    public void addHeader(NameValuePair header) {
         headers.add(header);
     }
 
-    public void addHeader(String name, String value){
-        headers.add(new NameValuePair(name,value));
+    public void addHeader(String name, String value) {
+        headers.add(new NameValuePair(name, value));
     }
 
     public String getContentType() {
@@ -96,5 +102,5 @@
     public void setContentLength(int contentLength) {
         this.contentLength = contentLength;
     }
-    
+
 }

Modified: geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpResponseDecoder.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpResponseDecoder.java?rev=568787&r1=568786&r2=568787&view=diff
==============================================================================
--- geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpResponseDecoder.java
(original)
+++ geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpResponseDecoder.java
Wed Aug 22 17:55:34 2007
@@ -34,24 +34,29 @@
     protected boolean doDecode(IoSession ioSession, ByteBuffer in, ProtocolDecoderOutput
out) throws Exception {
 
         HttpResponseMessage response = (HttpResponseMessage) ioSession.getAttribute(CURRENT_RESPONSE);
-        if (response == null){
+        if (response == null) {
             response = new HttpResponseMessage();
             ioSession.setAttribute(CURRENT_RESPONSE, response);
         }
 
         //Test if we need the response...
-        if (response.getStatusCode() == 0) {
-            //Read the status header
-            String header = httpDecoder.decodeLine(in);
-            if (header == null)
+        if (response.getState() == HttpResponseMessage.STATE_START) {
+
+            if (!processStatus(response, in)) {
                 return false;
+            }
 
-            httpDecoder.decodeStatus(header, response);
+            //Handle HTTP/1.1 100 Continue
+            if (response.getStatusCode() == 100) {
+                response.setState(HttpResponseMessage.STATE_STATUS_CONTINUE);
+            } else {
+                response.setState(HttpResponseMessage.STATE_STATUS_READ);
+            }
         }
 
-        //Have we read the headers yet?
-        if (!response.headersRead) {
-            //Read the headers and process them
+        //If we are in a 100 Continue, read until we get the real header
+        if (response.getState() == HttpResponseMessage.STATE_STATUS_CONTINUE) {
+            //Continue reading until we get a blank line
             while (true) {
                 String line = httpDecoder.decodeLine(in);
 
@@ -61,21 +66,37 @@
 
                 //Check if the entire response headers have been read
                 if (line.length() == 0) {
-                    response.headersRead = true;
+                    response.setState(HttpResponseMessage.STATE_STATUS_READ);
+
+                    //The next line should be a header
+                    if (!processStatus(response, in)) {
+                        return false;
+                    }
                     break;
                 }
-
-                httpDecoder.decodeHeader(line, response);
             }
         }
 
-        if (response.getContentLength() > 0) {
-            //Be sure all of the data is there for us to retrieve...
-            if ((response.getContentLength())  > in.remaining())
+        //Are we reading headers?
+        if (response.getState() == HttpResponseMessage.STATE_STATUS_READ) {
+            if (processHeaders(response, in) == false)
+               return false;
+        }
+
+        //Are we reading content?
+        if (response.getState() == HttpResponseMessage.STATE_HEADERS_READ) {
+            if (processContent(response, in) == false)
+                return false;
+        }
+
+        //If we are chunked and we have read all the content, then read the footers if there
are any
+        if (response.isChunked() && response.getState() == HttpResponseMessage.STATE_CONTENT_READ)
{
+            if (processFooters(response, in) == false)
                 return false;
-            httpDecoder.decodeContent(in, response);
         }
 
+        response.setState(HttpResponseMessage.STATE_FINISHED);
+
         out.write(response);
 
         ioSession.removeAttribute(CURRENT_RESPONSE);
@@ -83,4 +104,97 @@
         return true;
     }
 
+    private boolean processHeaders(HttpResponseMessage response, ByteBuffer in) throws Exception
{
+        if (!findHeaders(response, in))
+            return false;
+
+        response.setState(HttpResponseMessage.STATE_HEADERS_READ);
+        return true;
+    }
+
+    private boolean processFooters(HttpResponseMessage response, ByteBuffer in) throws Exception
{
+        if (!findHeaders(response, in))
+            return false;
+
+        response.setState(HttpResponseMessage.STATE_FOOTERS_READ);
+        return true;
+    }
+
+    private boolean findHeaders(HttpResponseMessage response, ByteBuffer in) throws Exception
{
+        //Read the headers and process them
+        while (true) {
+            String line = httpDecoder.decodeLine(in);
+
+            //Check if the entire response has been read
+            if (line == null)
+                return false;
+
+            //Check if the entire response headers have been read
+            if (line.length() == 0) {
+                break;
+            }
+
+            httpDecoder.decodeHeader(line, response);
+        }
+        return true;
+    }
+
+    private boolean processContent(HttpResponseMessage response, ByteBuffer in) throws Exception
{
+        if (response.isChunked()) {
+            while (true) {
+                //Check what kind of record we are reading (content or size)
+                if (response.getExpectedToRead() == HttpResponseMessage.EXPECTED_NOT_READ)
{
+                    //We haven't read the size, so we are expecting a size
+                    String line = httpDecoder.decodeLine(in);
+
+                    //Check if the entire line has been read
+                    if (line == null)
+                        return false;
+
+                    response.setExpectedToRead(httpDecoder.decodeSize(line));
+
+                    //Are we done reading the chunked content? (A zero means we are done)
+                    if (response.getExpectedToRead() == 0){
+                        break;
+                    }
+                }
+
+                //Now read the content chunk
+
+                //Be sure all of the data is there for us to retrieve + the CRLF...
+                if (response.getExpectedToRead() + 2 > in.remaining()){
+                    //Need more data
+                    return false;
+                }
+
+                //Read the content
+                httpDecoder.decodeChunkedContent(in, response);
+
+                //Flag that it's time to read a size record
+                response.setExpectedToRead(HttpResponseMessage.EXPECTED_NOT_READ);
+
+            }
+
+        } else if (response.getContentLength() > 0) {
+            //Do we have enough data?
+            if ((response.getContentLength()) > in.remaining())
+                return false;
+            httpDecoder.decodeContent(in, response);
+        }
+
+        response.setState(HttpResponseMessage.STATE_CONTENT_READ);
+
+        return true;
+    }
+
+    private boolean processStatus(HttpResponseMessage response, ByteBuffer in) throws Exception
{
+        //Read the status header
+        String header = httpDecoder.decodeLine(in);
+        if (header == null)
+            return false;
+
+        httpDecoder.decodeStatus(header, response);
+
+        return true;
+    }
 }

Modified: geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpResponseMessage.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpResponseMessage.java?rev=568787&r1=568786&r2=568787&view=diff
==============================================================================
--- geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpResponseMessage.java
(original)
+++ geronimo/sandbox/AsyncHttpClient/src/main/java/org/apache/ahc/codec/HttpResponseMessage.java
Wed Aug 22 17:55:34 2007
@@ -19,13 +19,26 @@
  */
 package org.apache.ahc.codec;
 
+import java.io.ByteArrayOutputStream;
+
 public class HttpResponseMessage extends HttpMessage {
 
+    static final int EXPECTED_NOT_READ = -1;
+    
+    static final int STATE_START = 0;
+    static final int STATE_STATUS_CONTINUE = 1;
+    static final int STATE_STATUS_READ = 2;
+    static final int STATE_HEADERS_READ = 3;
+    static final int STATE_CONTENT_READ = 4;
+    static final int STATE_FOOTERS_READ = 5;
+    static final int STATE_FINISHED = 6;
+    
     private int statusCode;
     private String statusMessage;
 
-    boolean headersRead = false;
-    boolean chunked = false;
+    private boolean chunked = false;
+    private int expectedToRead = -1;
+    private int state = STATE_START;
 
     public int getStatusCode() {
         return statusCode;
@@ -42,4 +55,29 @@
     public void setStatusMessage(String statusMessage) {
         this.statusMessage = statusMessage;
     }
+
+    boolean isChunked() {
+        return chunked;
+    }
+
+    void setChunked(boolean chunked) {
+        this.chunked = chunked;
+    }
+
+    int getExpectedToRead() {
+        return expectedToRead;
+    }
+
+    void setExpectedToRead(int expectedToRead) {
+        this.expectedToRead = expectedToRead;
+    }
+
+    int getState() {
+        return state;
+    }
+
+    void setState(int state) {
+        this.state = state;
+    }
+
 }

Added: geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/ChunkedTest.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/ChunkedTest.java?rev=568787&view=auto
==============================================================================
--- geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/ChunkedTest.java (added)
+++ geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/ChunkedTest.java Wed Aug
22 17:55:34 2007
@@ -0,0 +1,62 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.ahc;
+
+import junit.framework.TestCase;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+import org.apache.ahc.codec.HttpResponseDecoder;
+import org.apache.ahc.codec.HttpResponseMessage;
+
+import java.util.Arrays;
+
+public class ChunkedTest  extends TestCase {
+
+    private final static String fakeHttp =
+            "HTTP/1.1 200 OK\r\n" +
+                    "Date: Fri, 31 Dec 1999 23:59:59 GMT\r\n" +
+                    "Content-Type: text/plain\r\n" +
+                    "Transfer-Encoding: chunked\r\n" +
+                    "\r\n" +
+                    "1a; ignore-stuff-here\r\n" +
+                    "abcdefghijklmnopqrstuvwxyz\r\n" +
+                    "10\r\n" +
+                    "1234567890abcdef\r\n" +
+                    "0\r\n" +
+                    "some-footer: some-value\r\n" +
+                    "another-footer: another-value\r\n\r\n";
+
+
+    public void testChunking() throws Exception{
+        ByteBuffer buffer = ByteBuffer.allocate(fakeHttp.length());
+        buffer.put(fakeHttp.getBytes());
+        buffer.flip();
+
+        IoSession session = new FakeIoSession();
+        HttpResponseDecoder decoder = new HttpResponseDecoder();
+        FakeProtocolDecoderOutput out = new FakeProtocolDecoderOutput();
+        decoder.decode(session, buffer, out);
+        
+        HttpResponseMessage response = (HttpResponseMessage) out.getObject();
+        assertTrue(Arrays.equals(response.getContent(), "abcdefghijklmnopqrstuvwxyz1234567890abcdef".getBytes()));
+    }
+
+}

Added: geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/FakeIoSession.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/FakeIoSession.java?rev=568787&view=auto
==============================================================================
--- geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/FakeIoSession.java (added)
+++ geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/FakeIoSession.java Wed Aug
22 17:55:34 2007
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.ahc;
+
+import org.apache.mina.common.*;
+
+import java.util.Set;
+import java.util.Map;
+import java.util.HashMap;
+import java.net.SocketAddress;
+
+public class FakeIoSession implements IoSession {
+
+    private Map<String, Object> attributes = new HashMap<String, Object>();
+
+    public IoService getService() {
+        return null;
+    }
+
+    public IoServiceConfig getServiceConfig() {
+        return null;
+    }
+
+    public IoHandler getHandler() {
+        return null;
+    }
+
+    public IoSessionConfig getConfig() {
+        return null;
+    }
+
+    public IoFilterChain getFilterChain() {
+        return null;
+    }
+
+    public WriteFuture write(Object object) {
+        return null;
+    }
+
+    public CloseFuture close() {
+        return null;
+    }
+
+    public Object getAttachment() {
+        return null;
+    }
+
+    public Object setAttachment(Object object) {
+        return null;
+    }
+
+    public Object getAttribute(String string) {
+        return attributes.get(string);
+    }
+
+    public Object setAttribute(String string, Object object) {
+        return attributes.put(string, object);
+    }
+
+    public Object setAttribute(String string) {
+        return attributes.put(string, null);
+    }
+
+    public Object removeAttribute(String string) {
+        return attributes.remove(string);
+    }
+
+    public boolean containsAttribute(String string) {
+        return attributes.containsKey(string);
+    }
+
+    public Set<String> getAttributeKeys() {
+        return attributes.keySet();
+    }
+
+    public TransportType getTransportType() {
+        return null;
+    }
+
+    public boolean isConnected() {
+        return false;
+    }
+
+    public boolean isClosing() {
+        return false;
+    }
+
+    public CloseFuture getCloseFuture() {
+        return null;
+    }
+
+    public SocketAddress getRemoteAddress() {
+        return null;
+    }
+
+    public SocketAddress getLocalAddress() {
+        return null;
+    }
+
+    public SocketAddress getServiceAddress() {
+        return null;
+    }
+
+    public int getIdleTime(IdleStatus idleStatus) {
+        return 0;
+    }
+
+    public long getIdleTimeInMillis(IdleStatus idleStatus) {
+        return 0;
+    }
+
+    public void setIdleTime(IdleStatus idleStatus, int i) {
+    }
+
+    public int getWriteTimeout() {
+        return 0;
+    }
+
+    public long getWriteTimeoutInMillis() {
+        return 0;
+    }
+
+    public void setWriteTimeout(int i) {
+    }
+
+    public TrafficMask getTrafficMask() {
+        return null;
+    }
+
+    public void setTrafficMask(TrafficMask trafficMask) {
+    }
+
+    public void suspendRead() {
+    }
+
+    public void suspendWrite() {
+    }
+
+    public void resumeRead() {
+    }
+
+    public void resumeWrite() {
+    }
+
+    public long getReadBytes() {
+        return 0;
+    }
+
+    public long getWrittenBytes() {
+        return 0;
+    }
+
+    public long getReadMessages() {
+        return 0;
+    }
+
+    public long getWrittenMessages() {
+        return 0;
+    }
+
+    public long getWrittenWriteRequests() {
+        return 0;
+    }
+
+    public int getScheduledWriteRequests() {
+        return 0;
+    }
+
+    public int getScheduledWriteBytes() {
+        return 0;
+    }
+
+    public long getCreationTime() {
+        return 0;
+    }
+
+    public long getLastIoTime() {
+        return 0;
+    }
+
+    public long getLastReadTime() {
+        return 0;
+    }
+
+    public long getLastWriteTime() {
+        return 0;
+    }
+
+    public boolean isIdle(IdleStatus idleStatus) {
+        return false;
+    }
+
+    public int getIdleCount(IdleStatus idleStatus) {
+        return 0;
+    }
+
+    public long getLastIdleTime(IdleStatus idleStatus) {
+        return 0;
+    }
+}

Added: geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/FakeProtocolDecoderOutput.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/FakeProtocolDecoderOutput.java?rev=568787&view=auto
==============================================================================
--- geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/FakeProtocolDecoderOutput.java
(added)
+++ geronimo/sandbox/AsyncHttpClient/src/test/java/org/apache/ahc/FakeProtocolDecoderOutput.java
Wed Aug 22 17:55:34 2007
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.ahc;
+
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+
+public class FakeProtocolDecoderOutput implements ProtocolDecoderOutput {
+    
+    private Object object = null;
+
+    public void write(Object object) {
+        this.object = object;
+    }
+
+    public void flush() {
+    }
+
+
+    public Object getObject() {
+        return object;
+    }
+
+}



Mime
View raw message