geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jgenen...@apache.org
Subject svn commit: r607542 [3/6] - in /geronimo/sandbox/async-http-client-mina2: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/ahc/ src/main/java/org/apache/ahc/auth/ src/main/java/org/apache/ahc/codec/...
Date Sun, 30 Dec 2007 11:37:00 GMT
Added: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpDecoder.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpDecoder.java?rev=607542&view=auto
==============================================================================
--- geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpDecoder.java (added)
+++ geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpDecoder.java Sun Dec 30 03:36:47 2007
@@ -0,0 +1,321 @@
+/*
+ * 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.codec;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.util.Date;
+
+import org.apache.ahc.util.DateUtil;
+import org.apache.ahc.util.NameValuePair;
+import org.apache.mina.common.IoBuffer;
+
+/**
+ * Utility class for helping to decode the HTTP Protocol.
+ */
+public class HttpDecoder {
+
+    /** The Constant CHUNKED. */
+    public static final String CHUNKED = "chunked";
+
+    /** The Constant CONNECTION. */
+    public static final String CONNECTION = "Connection";
+    
+    /** The Constant CLOSE as a value for the Connection header */
+    public static final String CLOSE = "close";
+
+    /** The Constant COOKIE_COMMENT. */
+    public static final String COOKIE_COMMENT = "comment";
+    
+    /** The Constant COOKIE_DOMAIN. */
+    public static final String COOKIE_DOMAIN = "domain";
+    
+    /** The Constant COOKIE_EXPIRES. */
+    public static final String COOKIE_EXPIRES = "expires";
+    
+    /** The Constant COOKIE_MAX_AGE. */
+    public static final String COOKIE_MAX_AGE = "max-age";
+    
+    /** The Constant COOKIE_PATH. */
+    public static final String COOKIE_PATH = "path";
+    
+    /** The Constant COOKIE_SECURE. */
+    public static final String COOKIE_SECURE = "secure";
+    
+    /** The Constant COOKIE_VERSION. */
+    public static final String COOKIE_VERSION = "version";
+
+    /** The Constant LOCATION. */
+    public static final String LOCATION = "Location";
+    
+    /** The Constant SET_COOKIE. */
+    public static final String SET_COOKIE = "Set-Cookie";
+
+    /** The Constant WWW_AUTH. */
+    public static final String WWW_AUTH = "WWW-Authenticate";
+
+    /** The Constant TRANSFER_ENCODING. */
+    public static final String TRANSFER_ENCODING = "Transfer-Encoding";
+
+    /** Carriage return character. */
+    private static final byte CR = 13;
+
+    /** Line feed character. */
+    private static final byte LF = 10;
+
+
+    /** The decoder. */
+    private CharsetDecoder decoder = Charset.forName(HttpMessage.HTTP_ELEMENT_CHARSET).newDecoder();
+
+    /**
+     * Finds a line from a ByteBuffer that ends with a CR/LF and returns the line as a String.
+     * 
+     * @param in ByteBuffer containing data
+     * 
+     * @return a <code>String</code> representing the decoded line
+     * 
+     * @throws Exception for any Exception that is encountered
+     */
+    public String decodeLine(IoBuffer in) throws Exception {
+        int beginPos = in.position();
+        int limit = in.limit();
+        boolean lastIsCR = false;
+        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;
+            }
+        }
+
+        //Check if we don't have enough data to process or found a full readable line
+        if (terminatorPos == -1) {
+            return null;
+        }
+
+        String result = null;
+        if (terminatorPos > 1) {
+            IoBuffer line = in.slice();
+            line.limit(terminatorPos - beginPos - 1);
+            result = line.getString(decoder);
+        }
+
+        in.position(terminatorPos + 1);
+
+        return result;
+    }
+
+    /**
+     * Decodes the status code and message from a HTTP response and places the values in a
+     * {@link HttpResponseMessage} object.
+     * 
+     * @param line <code>String</code> containing <code>HTTP/1.<i>X</i> <i>Message</i></code>
+     * @param msg the <code>HttpResponseMessage</code> for which to place the result
+     * 
+     * @throws Exception on any Exception that may occur
+     * 
+     * @see HttpResponseMessage
+     */
+    public void decodeStatus(String line, HttpResponseMessage msg) throws Exception {
+        String magic = line.substring(0, 8);
+        if (!magic.equals("HTTP/1.1") && !magic.equals("HTTP/1.0")) {
+            throw new IOException("Invalid HTTP response");
+        }
+
+        String status = line.substring(9, 12);
+        msg.setStatusCode(Integer.parseInt(status));
+        msg.setStatusMessage(line.substring(13));
+    }
+
+    /**
+     * Decodes headers and footers (for HTTP/1.1) and stuffs them into a {@link HttpResponseMessage} response.
+     * 
+     * @param line the <code>String</code> line containing the header or footer
+     * @param msg the {@link HttpResponseMessage} response message
+     * 
+     * @throws Exception if any exception occurs
+     */
+    public void decodeHeader(String line, HttpResponseMessage msg) throws Exception {
+        int pos = line.indexOf(": ");
+        String name = line.substring(0, pos);
+        String value = line.substring(pos + 2);
+        NameValuePair nvp = new NameValuePair(name, value);
+        msg.addHeader(nvp);
+
+        if (name.equalsIgnoreCase(SET_COOKIE)) {
+            Cookie cookie = decodeCookie(value);
+            if (cookie != null) {
+                msg.addCookie(cookie);
+            }
+        }
+
+        if (name.equalsIgnoreCase(HttpMessage.CONTENT_TYPE)) {
+            msg.setContentType(value);
+        }
+
+        if (name.equalsIgnoreCase(HttpMessage.CONTENT_LENGTH)) {
+            msg.setContentLength(Integer.parseInt(value));
+        }
+
+        if (name.equalsIgnoreCase(CONNECTION)) {
+            msg.setConnection(value);
+        }
+
+        if (name.equalsIgnoreCase(LOCATION)) {
+            msg.setLocation(value);
+        }
+
+        if (name.equalsIgnoreCase(TRANSFER_ENCODING) && value != null && value.equalsIgnoreCase(CHUNKED)) {
+            msg.setChunked(true);
+        }
+
+        if (name.equalsIgnoreCase(WWW_AUTH)) {
+            msg.addChallenge(nvp);
+        }
+
+    }
+
+    /**
+     * Decodes size records for chunked HTTP transcoding.
+     * 
+     * @param line the line containing the size
+     * 
+     * @return the <code>int</code> representing the size
+     * 
+     * @throws Exception if any exception occurs
+     */
+    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);
+    }
+
+    /**
+     * Decodes content from non-chunked transcoding.
+     * 
+     * @param in the <code>ByteBuffer</code> containing the content at the the current position
+     * @param msg the <code>HttpResponseMessage</code> message to place the decoded content
+     * 
+     * @throws Exception if any exception occurs
+     */
+    public void decodeContent(IoBuffer in, HttpResponseMessage msg) throws Exception {
+        byte content[] = new byte[msg.getContentLength()];
+        in.get(content);
+        msg.addContent(content);
+    }
+
+    /**
+     * Decodes content from chunked transcoding.
+     * 
+     * @param in the <code>ByteBuffer</code> containing the content at the the current position
+     * @param msg the <code>HttpResponseMessage</code> message to place the decoded content
+     * 
+     * @throws Exception if any exception occurs
+     */
+    public void decodeChunkedContent(IoBuffer 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();
+    }
+
+    /**
+     * Decodes a cookie header and returns the decoded cookie.
+     * 
+     * @param cookieStr the cookie <code>String</code> header line
+     * 
+     * @return the decoded <code>Cookie</cookie>
+     * 
+     * @throws Exception if any exception occurs
+     * @see Cookie
+     */
+    public Cookie decodeCookie(String cookieStr) throws Exception {
+
+        Cookie cookie = null;
+
+        String pairs[] = cookieStr.split(";");
+        for (int i = 0; i < pairs.length; i++) {
+            String nameValue[] = pairs[i].trim().split("=");
+            String name = nameValue[0].trim();
+
+            //First one is the cookie name/value pair
+            if (i == 0) {
+                cookie = new Cookie(name, nameValue[1].trim());
+                continue;
+            }
+
+            if (name.equalsIgnoreCase(COOKIE_COMMENT)) {
+                cookie.setComment(nameValue[1].trim());
+                continue;
+            }
+
+            if (name.equalsIgnoreCase(COOKIE_PATH)) {
+                cookie.setPath(nameValue[1].trim());
+            }
+
+            if (name.equalsIgnoreCase(COOKIE_SECURE)) {
+                cookie.setSecure(true);
+            }
+
+            if (name.equalsIgnoreCase(COOKIE_VERSION)) {
+                cookie.setVersion(Integer.parseInt(nameValue[1]));
+            }
+
+            if (name.equalsIgnoreCase(COOKIE_MAX_AGE)) {
+                int age = Integer.parseInt(nameValue[1]);
+                cookie.setExpires(new Date(System.currentTimeMillis() + age * 1000L));
+            }
+
+            if (name.equalsIgnoreCase(COOKIE_EXPIRES)) {
+                cookie.setExpires(DateUtil.parseDate(nameValue[1]));
+            }
+
+            if (name.equalsIgnoreCase(COOKIE_DOMAIN)) {
+                cookie.setDomain(nameValue[1]);
+            }
+        }
+
+        return cookie;
+    }
+}

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpDecoder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpDecoder.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpDecoder.java
------------------------------------------------------------------------------
    svn:mime-type = text/x-java

Added: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpIoHandler.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpIoHandler.java?rev=607542&view=auto
==============================================================================
--- geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpIoHandler.java (added)
+++ geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpIoHandler.java Sun Dec 30 03:36:47 2007
@@ -0,0 +1,289 @@
+/*
+ *  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.codec;
+
+import java.net.URL;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.ahc.AsyncHttpClient;
+import org.apache.ahc.AsyncHttpClientCallback;
+import org.apache.ahc.auth.AuthChallengeParser;
+import org.apache.ahc.auth.AuthPolicy;
+import org.apache.ahc.auth.AuthScheme;
+import org.apache.ahc.auth.AuthState;
+import org.apache.ahc.util.NameValuePair;
+import org.apache.mina.common.IoHandlerAdapter;
+import org.apache.mina.common.IoSession;
+
+
+/**
+ * The Class HttpIoHandler.  Implements the MINA IoHandler interface as the primary
+ * event processor for the HTTP communication.
+ */
+public class HttpIoHandler extends IoHandlerAdapter {
+
+    /**
+     * The Constant CURRENT_REQUEST.
+     */
+    public static final String CURRENT_REQUEST = "CURRENT_REQUEST";
+
+    /**
+     * The Constant CURRENT_RESPONSE.
+     */
+    public static final String CURRENT_RESPONSE = "CURRENT_RESPONSE";
+    
+    /**
+     * The Constant CONNECTION_CLOSE.
+     */
+    public static final String CONNECTION_CLOSE = "close";
+
+    /**
+     * The scheduler service to handle timeouts.
+     */
+    private final ScheduledExecutorService scheduler;
+
+    /**
+     * Instantiates a new HttpIoHandler with a new a single-threaded executor.
+     */
+    public HttpIoHandler() {
+        this(Executors.newSingleThreadScheduledExecutor());
+    }
+
+    /**
+     * Instantiates a new HttpIoHandler with the supplied scheduler.
+     *
+     * @param scheduler the scheduler to use to track timeouts
+     */
+    public HttpIoHandler(ScheduledExecutorService scheduler) {
+        this.scheduler = scheduler;
+    }
+
+    /**
+     * Destroys the handler and shuts down the scheduler.
+     */
+    public void destroy() {
+        scheduler.shutdownNow();
+    }
+
+    /**
+     * Stub for handling sessionOpened events.
+     *
+     * @see org.apache.mina.common.IoHandlerAdapter#sessionOpened(org.apache.mina.common.IoSession)
+     */
+    public void sessionOpened(IoSession ioSession) throws Exception {
+    }
+
+    /**
+     * Handler for receiving a response from a remote server.
+     *
+     * @param ioSession the {@link org.apache.mina.common.IoSession} representing the connection to the server.
+     * @param object    the {@link HttpResponseMessage} object
+     * @see org.apache.mina.common.IoHandlerAdapter#messageReceived(org.apache.mina.common.IoSession,java.lang.Object)
+     */
+    @SuppressWarnings({"UnusedDeclaration"})
+    public void messageReceived(IoSession ioSession, Object object) throws Exception {
+
+        HttpResponseMessage response = (HttpResponseMessage) object;
+
+        HttpRequestMessage request = (HttpRequestMessage) ioSession.getAttribute(CURRENT_REQUEST);
+
+        //Check if we are to handle redirects
+        if ((response.getStatusCode() == 301
+             || response.getStatusCode() == 302
+             || response.getStatusCode() == 307)
+            && request.isFollowRedirects())
+        {
+            AsyncHttpClient client = (AsyncHttpClient) ioSession.getAttachment();
+
+            //Change the request url to the redirect
+            request.setUrl(new URL(response.getLocation()));
+            // if we're redirected via 30x, the request method should be reset to GET
+            if (!request.getRequestMethod().equals(HttpRequestMessage.REQUEST_GET)) {
+            	request.setRequestMethod(HttpRequestMessage.REQUEST_GET);
+            }
+            // we also need to clear out the parameters
+            request.clearAllParameters();
+
+            //Send the redirect
+            client.sendRequest(request);
+
+            // cache the session before we return
+            SessionCache.getInstance().cacheSession(ioSession);
+            return;
+        }
+
+        //Check if we have authentication
+        if (response.getChallenges().size() > 0) {
+            for (NameValuePair nvp : response.getChallenges()) {
+                AuthState state = request.getAuthState();
+                if (state == null) {
+                    String id = AuthChallengeParser.extractScheme(nvp.getValue());
+                    AuthScheme authScheme = AuthPolicy.getAuthScheme(id);
+                    state = new AuthState();
+                    state.setAuthScheme(authScheme);
+                    authScheme.processChallenge(nvp.getValue());
+                    request.setAuthState(state);
+                }
+            }
+
+            AsyncHttpClient client = (AsyncHttpClient) ioSession.getAttachment();
+
+            //Authenticate
+            int authCount = request.getAuthCount() + 1;
+            if (authCount <= 3) {
+                request.setAuthCount(authCount);
+                client.sendRequest(request);
+
+                // cache the session before we return
+                SessionCache.getInstance().cacheSession(ioSession);
+                return;
+            }
+        }
+
+        cancelTasks(request);
+
+        // complete the future which will also fire the callback
+        ResponseFuture result = request.getResponseFuture();
+        result.set(response);
+
+        // cache the session before we return
+        SessionCache.getInstance().cacheSession(ioSession);
+    }
+
+    /**
+     * Handler for receiving a notification that an Exception occurred in the communication with the server
+     *
+     * @param ioSession the {@link org.apache.mina.common.IoSession} representing the connection to the server.
+     * @param throwable the {@link java.lang.Throwable} object representing the exception that occurred
+     * @see org.apache.mina.common.IoHandlerAdapter#exceptionCaught(org.apache.mina.common.IoSession,java.lang.Throwable)
+     */
+    public void exceptionCaught(IoSession ioSession, Throwable throwable) throws Exception {
+        //Clean up if any in-proccess decoding was occurring
+        ioSession.removeAttribute(CURRENT_RESPONSE);
+
+        HttpRequestMessage request = (HttpRequestMessage) ioSession.getAttribute(CURRENT_REQUEST);
+        cancelTasks(request);
+
+        // complete the future which will also fire the callback
+        ResponseFuture result = request.getResponseFuture();
+        result.setException(throwable);
+
+        //Exception is bad, so just close it up
+        ioSession.close();
+    }
+
+    /**
+     * Handler for notifying that a connection was closed to the remote server.
+     *
+     * @param ioSession the {@link org.apache.mina.common.IoSession} representing the connection to the server.
+     * @see org.apache.mina.common.IoHandlerAdapter#sessionClosed(org.apache.mina.common.IoSession)
+     */
+    public void sessionClosed(IoSession ioSession) throws Exception {
+        //Clean up if any in-proccess decoding was occurring
+        ioSession.removeAttribute(CURRENT_RESPONSE);
+        // remove it from the cache
+        SessionCache.getInstance().removeSession(ioSession);
+        HttpRequestMessage request = (HttpRequestMessage) ioSession.getAttribute(CURRENT_REQUEST);
+        cancelTasks(request);
+        AsyncHttpClientCallback callback = request.getCallback();
+        if (callback != null) {
+            callback.onClosed();
+        }
+    }
+
+    /**
+     * Handler for notifying that a message was sent to a remote server.  It is responsible for setting up the
+     * timeout for a response from the remote server.
+     *
+     * @param ioSession the {@link org.apache.mina.common.IoSession} representing the connection to the server.
+     * @param object    the {@link HttpRequestMessage} object
+     * @see org.apache.mina.common.IoHandlerAdapter#messageSent(org.apache.mina.common.IoSession,java.lang.Object)
+     */
+    public void messageSent(IoSession ioSession, Object object) throws Exception {
+        HttpRequestMessage msg = (HttpRequestMessage) object;
+
+        //Start the timeout timer now if a timeout is needed and there is not one already in effect for this request
+        if (msg.getTimeOut() > 0 && msg.getTimeoutHandle() == null) {
+            TimeoutTask task = new TimeoutTask(ioSession);
+            ScheduledFuture handle = scheduler.schedule(task, msg.getTimeOut(), TimeUnit.MILLISECONDS);
+            msg.setTimeoutHandle(handle);
+        }
+    }
+
+    /**
+     * Utility function to cancel a request timeout task.
+     *
+     * @param request the {@link HttpRequestMessage} request
+     */
+    private void cancelTasks(HttpRequestMessage request) {
+        ScheduledFuture handle = request.getTimeoutHandle();
+        if (handle != null) {
+            boolean canceled = handle.cancel(true);
+            //See if it canceled
+            if (!canceled) {
+                //Couldn't cancel it and it ran, so too late :-(
+                return;
+            }
+            request.setTimeoutHandle(null);
+        }
+    }
+
+    /**
+     * The Class TimeoutTask.  Subclass that encapsulates handler for timeouts for the scheduler.
+     */
+    class TimeoutTask implements Runnable {
+
+        /**
+         * The session object.
+         */
+        private IoSession sess;
+
+        /**
+         * Instantiates a new timeout task.
+         *
+         * @param sess the {@link org.apache.mina.common.IoSession} representing the connection to the server.
+         */
+        public TimeoutTask(IoSession sess) {
+            this.sess = sess;
+        }
+
+        /**
+         * The running task which handles timing out the connection.
+         *
+         * @see java.lang.Runnable#run()
+         */
+        public void run() {
+            // complete the future which will also fire the callback
+            HttpRequestMessage request = (HttpRequestMessage)sess.getAttribute(CURRENT_REQUEST);
+            ResponseFuture result = request.getResponseFuture();
+            result.setException(new TimeoutException());
+            
+            //Close the session, its no good since the server is timing out
+            sess.close();
+        }
+
+    }
+
+
+}

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpIoHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpIoHandler.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpIoHandler.java
------------------------------------------------------------------------------
    svn:mime-type = text/x-java

Added: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpMessage.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpMessage.java?rev=607542&view=auto
==============================================================================
--- geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpMessage.java (added)
+++ geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpMessage.java Sun Dec 30 03:36:47 2007
@@ -0,0 +1,313 @@
+/*
+ *  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.codec;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.ahc.util.NameValuePair;
+
+/**
+ * The Class HttpMessage.  The base class for {@link HttpRequestMessage} and {@link HttpResponseMessage}.
+ */
+public class HttpMessage {
+
+    /** The Constant HTTP_ELEMENT_CHARSET used for encoding the HTTP elements. */
+    public static final String HTTP_ELEMENT_CHARSET = "US-ASCII";
+    
+    /** The Constant DEFAULT_URL_ENCODING_CHARSET use for URL encoding. */
+    public static final String DEFAULT_URL_ENCODING_CHARSET = "UTF-8";
+
+    /** The Constant CONTENT_TYPE. */
+    public static final String CONTENT_TYPE = "Content-Type";
+    
+    /** The Constant CONTENT_LENGTH. */
+    public static final String CONTENT_LENGTH = "Content-Length";
+
+    /** The headers associated with the message. */
+    protected List<NameValuePair> headers = new ArrayList<NameValuePair>();
+    
+    /** The cookies associated with the message. */
+    protected List<Cookie> cookies = new ArrayList<Cookie>();
+    
+    /** The content type. */
+    protected String contentType;
+    
+    /** The content length. */
+    protected int contentLength;
+    
+    /** The content container. */
+    protected ByteArrayOutputStream content;
+
+    /** The character charset for URL encoding **/
+    protected String urlEncodingCharset = DEFAULT_URL_ENCODING_CHARSET;
+
+    /**
+     * Gets the <code>String</code> content.  This method should only be
+     * used if the content is certain to be of type html or text as determined by the {@link #getContentType}. 
+     * 
+     * @return the <code>String</code> content or <code>null</code> if there is no content.
+     */
+    public String getStringContent() {
+        if (content == null) {
+            return null;
+        }
+
+        return new String(content.toByteArray());
+    }
+
+    /**
+     * Gets the content as a <code>byte[]</code> array.
+     * 
+     * @return the <code>byte[]</code> content or <code>null</code> if there is no content. 
+     */
+    public byte[] getContent() {
+        if (content == null) {
+            return null;
+        }
+
+        return content.toByteArray();
+    }
+
+    /**
+     * Appends <code>byte[]</code> to the content.
+     * 
+     * @param byteContent the byte content
+     * 
+     * @throws IOException Signals that an I/O exception has occurred.
+     */
+    public void addContent(byte[] byteContent) throws IOException {
+        if (this.content == null) {
+            this.content = new ByteArrayOutputStream();
+        }
+
+        this.content.write(byteContent);
+    }
+
+    /**
+     * Gets the cookies.
+     * 
+     * @return the cookies
+     */
+    public List<Cookie> getCookies() {
+        return cookies;
+    }
+
+    /**
+     * Sets the cookies.
+     * 
+     * @param cookies the new cookies
+     */
+    public void setCookies(List<Cookie> cookies) {
+        this.cookies = cookies;
+    }
+
+    /**
+     * Adds a cookie to the {@link Cookie} list.
+     * 
+     * @param cookie the cookie
+     */
+    public void addCookie(Cookie cookie) {
+        this.cookies.add(cookie);
+    }
+
+
+    /**
+     * Returns all headers.
+     * 
+     * @return all headers
+     */
+    public List<NameValuePair> getHeaders() {
+        return headers;
+    }
+
+    /**
+     * Sets the headers.  It removes any headers that were stored before the
+     * call.
+     * 
+     * @param headers the new headers
+     */
+    public void setHeaders(List<NameValuePair> headers) {
+        this.headers = headers;
+    }
+
+    /**
+     * Adds a header to the {@link org.apache.ahc.util.NameValuePair} header list.
+     * 
+     * @param header the header
+     */
+    public void addHeader(NameValuePair header) {
+        headers.add(header);
+    }
+
+    /**
+     * Adds the header as a <code>String</code> name/value pair to the 
+     * {@link org.apache.ahc.util.NameValuePair} header list.
+     * 
+     * @param name the name
+     * @param value the value
+     */
+    public void addHeader(String name, String value) {
+        headers.add(new NameValuePair(name, value));
+    }
+
+    /**
+     * Removes the headers that have the given name.
+     * 
+     * @param name the name
+     */
+    public void removeHeader(String name) {
+        Iterator<NameValuePair> it = headers.iterator();
+        while (it.hasNext()) {
+            NameValuePair header = it.next();
+            if (header.getName().equals(name)) {
+                it.remove();
+            }
+        }
+    }
+    
+    /**
+     * Sets the header with the given name and the value.  This differs from
+     * <code>addHeader()</code> in that it removes any existing header under the
+     * name and adds the new one.
+     * 
+     * @param name the name
+     * @param value the value
+     * @throws IllegalArgumentException if either the name or the value is null.
+     */
+    public void setHeader(String name, String value) {
+        if (name == null || value == null) {
+            throw new IllegalArgumentException("null name or value was passed in");
+        }
+        
+        // we're resetting the value, so remove it first
+        removeHeader(name);
+        addHeader(name, value);
+    }
+    
+    /**
+     * Returns the value for the header with the given name.  If there are more
+     * than one header stored, it returns the first entry it finds in the list.
+     * 
+     * @param name the name
+     * @return the value for the header, or null if it is not found
+     * @throws IllegalArgumentException if the name is null
+     */
+    public String getHeader(String name) {
+        if (name == null) {
+            throw new IllegalArgumentException("null name was passed in");
+        }
+        
+        Iterator<NameValuePair> it = headers.iterator();
+        while (it.hasNext()) {
+            NameValuePair header = it.next();
+            if (header.getName().equals(name)) {
+                return header.getValue();
+            }
+        }
+        return null;
+    }
+    
+    /**
+     * Returns an array of values for the header with the given name.
+     * 
+     * @param name the name
+     * @return the value for the header.  If there is no entry under the name,
+     * an empty array is returned.
+     * @throws IllegalArgumentException if the name is null
+     */
+    public String[] getHeaders(String name) {
+        if (name == null) {
+            throw new IllegalArgumentException("null name was passed in");
+        }
+        
+        List<String> values = new ArrayList<String>();
+        Iterator<NameValuePair> it = headers.iterator();
+        while (it.hasNext()) {
+            NameValuePair header = it.next();
+            if (header.getName().equals(name)) {
+                values.add(header.getValue());
+            }
+        }
+        return values.toArray(new String[]{});
+    }
+
+    /**
+     * Gets the content type.
+     * 
+     * @return the content type
+     */
+    public String getContentType() {
+        return contentType;
+    }
+
+    /**
+     * Sets the content type.
+     * 
+     * @param contentType the new content type
+     */
+    public void setContentType(String contentType) {
+        this.contentType = contentType;
+    }
+
+    /**
+     * Gets the content length.
+     * 
+     * @return the content length
+     */
+    public int getContentLength() {
+        return contentLength;
+    }
+
+    /**
+     * Sets the content length.
+     * 
+     * @param contentLength the new content length
+     */
+    public void setContentLength(int contentLength) {
+        this.contentLength = contentLength;
+    }
+    
+    /**
+     * Gets the charset that is used to do URL encoding/decoding.  It is
+     * "UTF-8" by default.
+     * 
+     * @return the charset name
+     */
+    public String getUrlEncodingCharset() {
+        return urlEncodingCharset;
+    }
+
+    /**
+     * Sets the charset that is used to do URL encoding/decoding.  In reality,
+     * the only recommended values are "UTF-8", and normally it is neither
+     * necessary nor recommended to use something other than the default.  <b>Do
+     * not reset this value</b> unless there is a very clear interoperability
+     * reason to do so.
+     * 
+     * @param charset the charset name
+     */
+    public void setUrlEncodingCharset(String charset) {
+        this.urlEncodingCharset = charset;
+    }
+}

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpMessage.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpMessage.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpMessage.java
------------------------------------------------------------------------------
    svn:mime-type = text/x-java

Added: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpProtocolCodecFactory.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpProtocolCodecFactory.java?rev=607542&view=auto
==============================================================================
--- geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpProtocolCodecFactory.java (added)
+++ geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpProtocolCodecFactory.java Sun Dec 30 03:36:47 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.codec;
+
+import org.apache.mina.filter.codec.ProtocolCodecFactory;
+import org.apache.mina.filter.codec.ProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.common.IoSession;
+
+/**
+ * A factory for creating {@link HttpRequestEncoder} and {@link HttpResponseDecoder} objects.
+ */
+public class HttpProtocolCodecFactory implements ProtocolCodecFactory {
+
+    /** The encoder. */
+    private final ProtocolEncoder encoder;
+    
+    /** The decoder. */
+    private final ProtocolDecoder decoder;
+
+    /**
+     * Instantiates a new HttpProtocolCodecFactory.
+     */
+    public HttpProtocolCodecFactory() {
+        encoder = new HttpRequestEncoder();
+        decoder = new HttpResponseDecoder();
+    }
+
+    /**
+     * Returns the {@link org.apache.mina.filter.codec.ProtocolEncoder} encoder.
+     * 
+     */
+    public ProtocolEncoder getEncoder(IoSession ioSession) throws Exception {
+        return encoder;
+    }
+
+    /**
+     * Returns the {@link org.apache.mina.filter.codec.ProtocolDecoder} encoder.
+     * 
+     */
+    public ProtocolDecoder getDecoder(IoSession ioSession) throws Exception {
+        return decoder;
+    }
+
+}

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpProtocolCodecFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpProtocolCodecFactory.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpProtocolCodecFactory.java
------------------------------------------------------------------------------
    svn:mime-type = text/x-java

Added: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpRequestEncoder.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpRequestEncoder.java?rev=607542&view=auto
==============================================================================
--- geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpRequestEncoder.java (added)
+++ geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpRequestEncoder.java Sun Dec 30 03:36:47 2007
@@ -0,0 +1,244 @@
+/*
+ *  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.codec;
+
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.ahc.auth.AuthScope;
+import org.apache.ahc.auth.AuthState;
+import org.apache.ahc.util.EncodingUtil;
+import org.apache.ahc.util.NameValuePair;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.common.IoBuffer;
+import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+
+/**
+ * The Class HttpRequestEncoder. This handles the encoding of an {@link HttpRequestMessage} into
+ * raw bytes.
+ */
+public class HttpRequestEncoder extends ProtocolEncoderAdapter {
+    
+    /** The Constant TYPES. */
+    private static final Set<Class<?>> TYPES;
+    
+    /** The Constant CRLF. */
+    private static final byte[] CRLF = new byte[] {0x0D, 0x0A};
+    
+    /** The Constant POST_CONTENT_TYPE. */
+    private static final String POST_CONTENT_TYPE = "application/x-www-form-urlencoded";
+
+    static {
+        Set<Class<?>> types = new HashSet<Class<?>>();
+        types.add(HttpRequestMessage.class);
+        TYPES = Collections.unmodifiableSet(types);
+    }
+
+    /**
+     * Instantiates a new http request encoder.
+     */
+    public HttpRequestEncoder() {
+    }
+
+    /**
+     * Gets the message types for the MINA infrastructure.
+     * 
+     * @return the message types
+     */
+    public Set<Class<?>> getMessageTypes() {
+        return TYPES;
+    }
+
+    /**
+     * Method responsible for encoding a HttpRequestMessage into raw bytes.
+     * 
+     * @param ioSession the {@link org.apache.mina.common.IoSession} representing the connection to the server.
+     * @param message the {@link HttpRequestMessage} object
+     * @param out {@link org.apache.mina.filter.codec.ProtocolEncoderOutput} used for output
+     * @see org.apache.mina.filter.codec.ProtocolEncoder#encode(org.apache.mina.common.IoSession, java.lang.Object, org.apache.mina.filter.codec.ProtocolEncoderOutput)
+     */
+    public void encode(IoSession ioSession, Object message, ProtocolEncoderOutput out) throws Exception {
+        HttpRequestMessage msg = (HttpRequestMessage)message;
+
+        IoBuffer buf = IoBuffer.allocate(1024, false);
+
+        // Enable auto-expand for easier encoding
+        buf.setAutoExpand(true);
+
+        try {
+            //If we have content, lets create the query string
+            int attrCount = msg.getParameters().size();
+            String urlAttrs = "";
+            if (attrCount > 0) {
+                NameValuePair attrs[] = new NameValuePair[attrCount];
+                Set<Map.Entry<String, String>> set = msg.getParameters().entrySet();
+                int i = 0;
+                for (Map.Entry<String, String> entry : set) {
+                    attrs[i++] = new NameValuePair(entry.getKey(), entry.getValue());
+                }
+                urlAttrs = EncodingUtil.formUrlEncode(attrs, msg.getUrlEncodingCharset());
+            }
+
+            CharsetEncoder encoder = Charset.forName(HttpMessage.HTTP_ELEMENT_CHARSET).newEncoder();
+            buf.putString(msg.getRequestMethod(), encoder);
+            buf.putString(" ", encoder);
+            buf.putString(msg.getPath(), encoder);
+            //If its a GET, append the attributes
+            if (msg.getRequestMethod().equals(HttpRequestMessage.REQUEST_GET) && attrCount > 0) {
+                //If there is not already a ? in the query, append one, otherwise append a &
+                if (!msg.getPath().contains("?")) {
+                    buf.putString("?", encoder);
+                } else {
+                    buf.putString("&", encoder);
+                }
+                buf.putString(urlAttrs, encoder);
+            }
+            buf.putString(" HTTP/1.1", encoder);
+            buf.put(CRLF);
+
+            //This header is required for HTTP/1.1
+            buf.putString("Host: ", encoder);
+            buf.putString(msg.getHost(), encoder);
+            if ((msg.getProtocol().equals("http") && msg.getPort() != 80)
+                || (msg.getProtocol().equals("https") && msg.getPort() != 443)) {
+                buf.putString(":", encoder);
+                buf.putString(msg.getPort() + "", encoder);
+            }
+            buf.put(CRLF);
+
+            //User agent
+            if (msg.getUserAgent() != null) {
+                buf.putString("User-Agent: ", encoder);
+                buf.putString(msg.getUserAgent(), encoder);
+                buf.put(CRLF);
+            }
+
+            //Process any headers we have
+            processHeaders(msg, buf, encoder);
+
+            //Process cookies
+            //NOTE: I am just passing the name value pairs and not doing management of the expiration or path
+            //As that will be left up to the user.  A possible enhancement is to make use of a CookieManager
+            //to handle these issues for the request
+            processCookies(msg, buf, encoder);
+
+            //If this is a POST, then we need a content length and type
+            if (msg.getRequestMethod().equals(HttpRequestMessage.REQUEST_POST)) {
+                byte content[] = urlAttrs.getBytes();
+
+                //Type
+                buf.putString(HttpMessage.CONTENT_TYPE, encoder);
+                buf.putString(": ", encoder);
+                buf.putString(POST_CONTENT_TYPE, encoder);
+                buf.put(CRLF);
+
+                //Length
+                buf.putString(HttpMessage.CONTENT_LENGTH, encoder);
+                buf.putString(": ", encoder);
+                buf.putString(content.length + "", encoder);
+                buf.put(CRLF);
+                //Blank line
+                buf.put(CRLF);
+                buf.put(content);
+            } else {
+                //Blank line
+                buf.put(CRLF);
+            }
+
+        } catch (CharacterCodingException ex) {
+            ex.printStackTrace();
+        }
+
+        buf.flip();
+
+        out.write(buf);
+        out.flush();
+
+    }
+
+    /**
+     * Process header encoding.
+     * 
+     * @param msg the {@link HttpRequestMessage} message object
+     * @param buf the <code>ByteBuffer</code> in which to place the raw bytes
+     * @param encoder the character set encoder
+     * 
+     * @throws Exception if any exception occurs.
+     */
+    private void processHeaders(HttpRequestMessage msg, IoBuffer buf, CharsetEncoder encoder)
+        throws Exception {
+        List<NameValuePair> headers = msg.getHeaders();
+        for (NameValuePair header : headers) {
+            String name = header.getName();
+            String value = header.getValue();
+
+            buf.putString(name, encoder);
+            buf.putString(": ", encoder);
+            buf.putString(value, encoder);
+            buf.put(CRLF);
+        }
+
+        //Process authentication
+        AuthState state = msg.getAuthState();
+        if (state != null){
+            String auth = state.getAuthScheme().authenticate(msg.getCredential(new AuthScope(msg.getHost(), msg.getPort(), state.getAuthScheme().getRealm())),msg);
+            buf.putString("Authorization", encoder);
+            buf.putString(": ", encoder);
+            buf.putString(auth, encoder);
+            buf.put(CRLF);
+            state.setAuthAttempted(true);
+        }
+    }
+
+    /**
+     * Process cookies.
+     * 
+     * @param msg the msg
+     * @param buf the buf
+     * @param encoder the encoder
+     * 
+     * @throws Exception the exception
+     */
+    private void processCookies(HttpRequestMessage msg, IoBuffer buf, CharsetEncoder encoder)
+        throws Exception {
+        List<Cookie> cookies = msg.getCookies();
+        if (cookies.size() > 0) {
+            buf.putString("Cookie: ", encoder);
+            for (Cookie cookie : cookies) {
+                String name = cookie.getName();
+                String value = cookie.getValue();
+
+                buf.putString(name, encoder);
+                buf.putString("=", encoder);
+                buf.putString(value, encoder);
+                buf.putString("; ", encoder);
+            }
+            buf.put(CRLF);
+        }
+    }
+
+}

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpRequestEncoder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpRequestEncoder.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpRequestEncoder.java
------------------------------------------------------------------------------
    svn:mime-type = text/x-java

Added: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpRequestMessage.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpRequestMessage.java?rev=607542&view=auto
==============================================================================
--- geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpRequestMessage.java (added)
+++ geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpRequestMessage.java Sun Dec 30 03:36:47 2007
@@ -0,0 +1,542 @@
+/*
+ *  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.codec;
+
+import java.net.ProtocolException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.ScheduledFuture;
+
+import javax.net.ssl.SSLContext;
+
+import org.apache.ahc.AsyncHttpClientCallback;
+import org.apache.ahc.auth.AuthScope;
+import org.apache.ahc.auth.AuthState;
+import org.apache.ahc.auth.Credentials;
+
+/**
+ * The Class HttpRequestMessage. This is an object representation of an HTTP request.
+ */
+public class HttpRequestMessage extends HttpMessage {
+
+    /**
+     * The Constant DEFAULT_REQUEST_TIMEOUT.
+     */
+    public static final int DEFAULT_REQUEST_TIMEOUT = 30000;
+
+    /**
+     * The Constant DEFAULT_CREDENTIAL_CHARSET.
+     */
+    public static final String DEFAULT_CREDENTIAL_CHARSET = "US-ASCII";
+
+    /**
+     * The Constant REQUEST_GET.
+     */
+    public static final String REQUEST_GET = "GET";
+
+    /**
+     * The Constant REQUEST_POST.
+     */
+    public static final String REQUEST_POST = "POST";
+
+    /**
+     * The Constant REQUEST_HEAD.
+     */
+    public static final String REQUEST_HEAD = "HEAD";
+
+    /**
+     * The Constant REQUEST_OPTIONS.
+     */
+    public static final String REQUEST_OPTIONS = "OPTIONS";
+
+    /**
+     * The Constant REQUEST_PUT.
+     */
+    public static final String REQUEST_PUT = "PUT";
+
+    /**
+     * The Constant REQUEST_DELETE.
+     */
+    public static final String REQUEST_DELETE = "DELETE";
+
+    /**
+     * The Constant REQUEST_TRACE.
+     */
+    public static final String REQUEST_TRACE = "TRACE";
+
+    /**
+     * The request method.
+     */
+    private String requestMethod = REQUEST_GET;
+
+    /**
+     * The request url.
+     */
+    private URL url;
+
+    /**
+     * The parameters.
+     */
+    private Map<String, String> parameters = new HashMap<String, String>();
+
+    /**
+     * The user agent.
+     */
+    private String userAgent = "AsyncHttpClient 1.0";
+
+    /**
+     * The follow redirects.
+     */
+    private boolean followRedirects = true;
+
+    /**
+     * The timeout handle.
+     */
+    private ScheduledFuture timeoutHandle;
+
+    /**
+     * The response future.
+     */
+    private volatile ResponseFuture responseFuture;
+    
+    /**
+     * The callback.
+     */
+    private AsyncHttpClientCallback callback;
+
+    /**
+     * The time out.
+     */
+    private int timeOut = DEFAULT_REQUEST_TIMEOUT;
+
+    /**
+     * The character credential charset *
+     */
+    protected String credentialCharset = DEFAULT_CREDENTIAL_CHARSET;
+
+    /**
+     * The challenge map *
+     */
+    private AuthState authState;
+
+    /**
+     * The credentials map *
+     */
+    private HashMap<AuthScope, Credentials> credentials = new HashMap<AuthScope, Credentials>();
+
+
+    /**
+     * Auth attempt count
+     */
+    private int authCount = 0;
+    
+    /**
+     * SSL context for https
+     */
+    private SSLContext sslContext;
+
+    /**
+     * Instantiates a new http request message.
+     *
+     * @param url      the complete url for which the request including scheme, host, port[optional], and query
+     *                 (i.e. <code>http://www.example.com:8080/example.cgi?test=me</code>).
+     * @param callback the {@link org.apache.ahc.AsyncHttpClientCallback} callback class to receive notifications when they occur.
+     */
+    public HttpRequestMessage(URL url, AsyncHttpClientCallback callback) {
+        this.url = url;
+        this.callback = callback;
+    }
+
+    /**
+     * Gets the time out.
+     *
+     * @return the time out in milliseconds.  Defaults to {@link #DEFAULT_REQUEST_TIMEOUT} if not set.
+     */
+    public int getTimeOut() {
+        return timeOut;
+    }
+
+    /**
+     * Sets the time out.
+     *
+     * @param timeOut the new time out in milliseconds. Defaults to {@link #DEFAULT_REQUEST_TIMEOUT} if not set.
+     */
+    public void setTimeOut(int timeOut) {
+        this.timeOut = timeOut;
+    }
+
+    /**
+     * Gets the timeout handle.
+     *
+     * @return the timeout <code>ScheduledFuture</code> handle
+     */
+    protected ScheduledFuture getTimeoutHandle() {
+        return timeoutHandle;
+    }
+
+    /**
+     * Sets the timeout handle.
+     *
+     * @param timeoutHandle the new <code>ScheduledFuture</code> timeout handle
+     */
+    protected void setTimeoutHandle(ScheduledFuture timeoutHandle) {
+        this.timeoutHandle = timeoutHandle;
+    }
+
+    /**
+     * Gets the request method.
+     *
+     * @return the request method.  Defaults to {@link #REQUEST_GET} if not set.
+     */
+    public String getRequestMethod() {
+        return requestMethod;
+    }
+
+    /**
+     * Returns the response future object associated with the request.
+     */
+    public ResponseFuture getResponseFuture() {
+        return responseFuture;
+    }
+
+    /**
+     * Sets the response future object.
+     */
+    public void setResponseFuture(ResponseFuture result) {
+        responseFuture = result;
+    }
+
+    /**
+     * Gets the callback.
+     *
+     * @return the {@link org.apache.ahc.AsyncHttpClientCallback} callback
+     */
+    public AsyncHttpClientCallback getCallback() {
+        return callback;
+    }
+
+    /**
+     * Sets the request method.
+     *
+     * @param requestMethod the new request method
+     * @throws ProtocolException if the request method is not of type {@link #REQUEST_GET},
+     *                           {@link #REQUEST_POST},{@link #REQUEST_HEAD},{@link #REQUEST_OPTIONS},
+     *                           {@link #REQUEST_PUT},{@link #REQUEST_DELETE}, or {@link #REQUEST_TRACE}
+     */
+    public void setRequestMethod(String requestMethod) throws ProtocolException {
+        if (requestMethod.equals(REQUEST_GET)
+            || requestMethod.equals(REQUEST_POST)
+            || requestMethod.equals(REQUEST_HEAD)
+            || requestMethod.equals(REQUEST_OPTIONS)
+            || requestMethod.equals(REQUEST_PUT)
+            || requestMethod.equals(REQUEST_DELETE)
+            || requestMethod.equals(REQUEST_TRACE)) {
+            this.requestMethod = requestMethod;
+            return;
+        }
+
+        throw new ProtocolException("Invalid request method type.");
+    }
+
+    /**
+     * Gets the url.
+     *
+     * @return the url
+     */
+    public URL getUrl() {
+        return url;
+    }
+
+    /**
+     * Sets the url.
+     *
+     * @param url the new url
+     */
+    public void setUrl(URL url) {
+        this.url = url;
+    }
+
+    /**
+     * Gets the path part of the url.
+     *
+     * @return the path part of the url
+     */
+    public String getPath() {
+        return url.getPath();
+    }
+
+    /**
+     * Gets the host part of the url.
+     *
+     * @return the host part of the url
+     */
+    public String getHost() {
+        return url.getHost();
+    }
+
+    /**
+     * Gets the port part of the url.
+     *
+     * @return the port part of the url
+     */
+    public int getPort() {
+        String scheme = url.getProtocol();
+        int port = url.getPort();
+        if (scheme.toLowerCase().equals("https")) {
+            if (port == -1) {
+                port = 443;
+            }
+        }
+        if (scheme.toLowerCase().equals("http") && (port == -1)) {
+            port = 80;
+        }
+        return port;
+    }
+
+    /**
+     * Gets the protocol part of the url.
+     *
+     * @return the protocol part of the url
+     */
+    public String getProtocol() {
+        return url.getProtocol();
+    }
+
+    /**
+     * Gets the query part of the url.
+     *
+     * @return the query part of the url
+     */
+    public String getQuery() {
+        return url.getQuery();
+    }
+
+    /**
+     * Gets a parameter from the parameter map.
+     *
+     * @param name the parameter name
+     * @return the parameter value
+     */
+    public String getParameter(String name) {
+        return parameters.get(name);
+    }
+
+    /**
+     * Gets the parameter map.
+     *
+     * @return the parameter map
+     */
+    public Map<String, String> getParameters() {
+        return parameters;
+    }
+
+    /**
+     * Sets the parameter map.
+     *
+     * @param parameters the parameter map
+     */
+    public void setParameters(Map<String, String> parameters) {
+        this.parameters.putAll(parameters);
+    }
+
+    /**
+     * Sets a single parameter.
+     *
+     * @param name  the parameter name
+     * @param value the value of parameter
+     */
+    public void setParameter(String name, String value) {
+        parameters.put(name, value);
+    }
+    
+    /**
+     * Clears all parameters.
+     *
+     */
+    public void clearAllParameters() {
+        parameters.clear();
+    }
+
+    /**
+     * Gets the user agent string.
+     *
+     * @return the user agent <code>String</code>
+     */
+    public String getUserAgent() {
+        return userAgent;
+    }
+
+    /**
+     * Sets the user agent string.
+     *
+     * @param userAgent the new user agent <code>String</code>
+     */
+    public void setUserAgent(String userAgent) {
+        this.userAgent = userAgent;
+    }
+
+    /**
+     * Checks if the request will follow redirects (301,302 and 307 HTTP status).
+     *
+     * @return <code>true</code>, if the request will follow redirects, <code>false</code> if not.
+     *         Defaults to <code>true</code> if not set.
+     */
+    public boolean isFollowRedirects() {
+        return followRedirects;
+    }
+
+    /**
+     * Sets whether the request will follow redirects (301,302 and 307 HTTP status).
+     *
+     * @param followRedirects the new follow redirects.  Set to <code>true</code>, if the request
+     *                        will follow redirects, <code>false</code> if not.
+     */
+    public void setFollowRedirects(boolean followRedirects) {
+        this.followRedirects = followRedirects;
+    }
+
+    /**
+     * Gets the credential character set
+     *
+     * @return the credential character set. Defaults to {@link #DEFAULT_CREDENTIAL_CHARSET} if not set.
+     */
+    public String getCredentialCharset() {
+        return credentialCharset;
+    }
+
+    /**
+     * Sets the credential character set
+     *
+     * @param credentialCharset the new credential character set
+     */
+    public void setCredentialCharset(String credentialCharset) {
+        this.credentialCharset = credentialCharset;
+    }
+
+    /**
+     * Gets the authorization state
+     *
+     * @return the authorization state
+     */
+    public AuthState getAuthState() {
+        return authState;
+    }
+
+    /**
+     * Sets the authorization state
+     *
+     * @param authState the authorization state
+     */
+    public void setAuthState(AuthState authState) {
+        this.authState = authState;
+    }
+
+    /**
+     * Gets the credentials map
+     *
+     * @return the credential map
+     */
+    public HashMap<AuthScope, Credentials> getCredentials() {
+        return credentials;
+    }
+
+    /**
+     * Gets a single credential
+     *
+     * @param scope the (@link org.apache.ahc.AuthScope} object
+     * @return (@linkorg.apache.ahc.Credentials} objectiffoundor <code>null</code> ifnotfound
+     */
+    public Credentials getCredential(AuthScope scope) {
+        return matchCredentials(credentials, scope);
+    }
+
+    private static Credentials matchCredentials(final HashMap map, final AuthScope authscope) {
+        // see if we get a direct hit
+        Credentials creds = (Credentials)map.get(authscope);
+        if (creds == null) {
+            // Nope.
+            // Do a full scan
+            int bestMatchFactor = -1;
+            AuthScope bestMatch = null;
+            Iterator items = map.keySet().iterator();
+            while (items.hasNext()) {
+                AuthScope current = (AuthScope)items.next();
+                int factor = authscope.match(current);
+                if (factor > bestMatchFactor) {
+                    bestMatchFactor = factor;
+                    bestMatch = current;
+                }
+            }
+            if (bestMatch != null) {
+                creds = (Credentials)map.get(bestMatch);
+            }
+        }
+        return creds;
+    }
+
+    /**
+     * Adds a credential
+     *
+     * @param scope       the (@link org.apache.ahc.AuthScope} object
+     * @param credentials (@link org.apache.ahc.Credentials} object
+     */
+    public void addCredentials(AuthScope scope, Credentials credentials) {
+        this.credentials.put(scope, credentials);
+    }
+
+
+    /**
+     * Gets the authorization attempt count
+     *
+     * @return the authorization attempt count
+     */
+    public int getAuthCount() {
+        return authCount;
+    }
+
+    /**
+     * Sets the authorization attempt count
+     * 
+     * @param authCount the authorization attempt count
+     */
+    public void setAuthCount(int authCount) {
+        this.authCount = authCount;
+    }
+    
+    /**
+     * Gets the SSL context
+     * 
+     * @return the SSL context
+     */
+    public SSLContext getSSLContext() {
+        return sslContext;
+    }
+    
+    /**
+     * Sets the SSL context
+     * 
+     * @param sslContext the SSL context
+     */
+    public void setSSLContext(SSLContext sslContext) {
+        this.sslContext = sslContext;
+    }
+}

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpRequestMessage.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpRequestMessage.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpRequestMessage.java
------------------------------------------------------------------------------
    svn:mime-type = text/x-java

Added: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpResponseDecoder.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpResponseDecoder.java?rev=607542&view=auto
==============================================================================
--- geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpResponseDecoder.java (added)
+++ geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpResponseDecoder.java Sun Dec 30 03:36:47 2007
@@ -0,0 +1,279 @@
+/*
+ *  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.codec;
+
+import org.apache.ahc.util.NeedMoreDataException;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.common.IoBuffer;
+import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+
+/**
+ * The Class HttpResponseDecoder. This handles the decoding of raw bytes into a
+ * {@link HttpResponseMessage} object.
+ */
+public class HttpResponseDecoder extends CumulativeProtocolDecoder {
+
+    /** The http decoder. */
+    private HttpDecoder httpDecoder = new HttpDecoder();
+
+    /**
+     * Decodes the raw HTTP response from a server into a {@link HttpResponseMessage} object.
+     * 
+     * @param ioSession the {@link org.apache.mina.common.IoSession} representing the connection to the server.
+     * @param in the <code>ByteBuffer</code> that contains the raw bytes from the server
+     * @param out {@link org.apache.mina.filter.codec.ProtocolDecoderOutput} used for output
+     * 
+     * @return <code>true</code> if it can read all of the data, or <code>false</code> if not.  A false tells the API to fetch more data.
+     * 
+     */
+    protected boolean doDecode(IoSession ioSession, IoBuffer in, ProtocolDecoderOutput out)
+        throws Exception {
+
+        try {
+            HttpResponseMessage response = (HttpResponseMessage)ioSession.getAttribute(HttpIoHandler.CURRENT_RESPONSE);
+            if (response == null) {
+                response = new HttpResponseMessage();
+                ioSession.setAttribute(HttpIoHandler.CURRENT_RESPONSE, response);
+            }
+
+            //Test if we need the response...
+            if (response.getState() == HttpResponseMessage.STATE_START) {
+
+                if (!processStatus(response, in)) {
+                    throw new NeedMoreDataException();
+                }
+
+                //Handle HTTP/1.1 100 Continue
+                if (response.getStatusCode() == 100) {
+                    response.setState(HttpResponseMessage.STATE_STATUS_CONTINUE);
+                } else {
+                    response.setState(HttpResponseMessage.STATE_STATUS_READ);
+                }
+            }
+
+            //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);
+
+                    //Check if the entire response has been read
+                    if (line == null) {
+                        throw new NeedMoreDataException();
+                    }
+
+                    //Check if the entire response headers have been read
+                    if (line.length() == 0) {
+                        response.setState(HttpResponseMessage.STATE_STATUS_READ);
+
+                        //The next line should be a header
+                        if (!processStatus(response, in)) {
+                            throw new NeedMoreDataException();
+                        }
+                        break;
+                    }
+                }
+            }
+
+            //Are we reading headers?
+            if (response.getState() == HttpResponseMessage.STATE_STATUS_READ) {
+                if (!processHeaders(response, in)) {
+                    throw new NeedMoreDataException();
+                }
+            }
+
+            //Are we reading content?
+            if (response.getState() == HttpResponseMessage.STATE_HEADERS_READ) {
+                if (!processContent(response, in)) {
+                    throw new NeedMoreDataException();
+                }
+            }
+
+            //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)) {
+                    throw new NeedMoreDataException();
+                }
+            }
+
+            response.setState(HttpResponseMessage.STATE_FINISHED);
+
+            out.write(response);
+
+            ioSession.removeAttribute(HttpIoHandler.CURRENT_RESPONSE);
+
+            return true;
+        } catch (NeedMoreDataException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Reads the headers and processes them as header objects in the {@link HttpResponseMessage} object.
+     * 
+     * @param response the {@link HttpResponseMessage} response object
+     * @param in the <code>ByteBuffer</code> that contains the raw bytes from the server
+     * 
+     * @return <code>true</code> if it can read all of the data, or <code>false</code> if not.
+     * 
+     * @throws Exception if any exception occurs
+     */
+    private boolean processHeaders(HttpResponseMessage response, IoBuffer in) throws Exception {
+        if (!findHeaders(response, in)) {
+            return false;
+        }
+
+        response.setState(HttpResponseMessage.STATE_HEADERS_READ);
+        return true;
+    }
+
+    /**
+     * Reads the footers and processes them as header objects in the {@link HttpResponseMessage} 
+     * object.  This is only used in chunked transcoding.
+     * 
+     * @param response the {@link HttpResponseMessage} response object
+     * @param in the <code>ByteBuffer</code> that contains the raw bytes from the server
+     * 
+     * @return <code>true</code> if it can read all of the data, or <code>false</code> if not.
+     * 
+     * @throws Exception if any exception occurs
+     */
+    private boolean processFooters(HttpResponseMessage response, IoBuffer in) throws Exception {
+        if (!findHeaders(response, in)) {
+            return false;
+        }
+
+        response.setState(HttpResponseMessage.STATE_FOOTERS_READ);
+        return true;
+    }
+
+    /**
+     * Decodes the raw headers/footers.
+     * 
+     * @param response the {@link HttpResponseMessage} response object
+     * @param in the <code>ByteBuffer</code> that contains the raw bytes from the server
+     * 
+     * @return <code>true</code> if it can read all of the data, or <code>false</code> if not.
+     * 
+     * @throws Exception if any exception occurs
+     */
+    private boolean findHeaders(HttpResponseMessage response, IoBuffer 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;
+    }
+
+    /**
+     * Process and read the content.
+     * 
+     * @param response the {@link HttpResponseMessage} response object
+     * @param in the <code>ByteBuffer</code> that contains the raw bytes from the server
+     * 
+     * @return <code>true</code> if it can read all of the data, or <code>false</code> if not.
+     * 
+     * @throws Exception if any exception occurs
+     */
+    private boolean processContent(HttpResponseMessage response, IoBuffer 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;
+    }
+
+    /**
+     * Process  and read the status header.
+     * 
+     * @param response the {@link HttpResponseMessage} response object
+     * @param in the <code>ByteBuffer</code> that contains the raw bytes from the server
+     * 
+     * @return <code>true</code> if it can read all of the data, or <code>false</code> if not.
+     * 
+     * @throws Exception if any exception occurs
+     */
+    private boolean processStatus(HttpResponseMessage response, IoBuffer in) throws Exception {
+        //Read the status header
+        String header = httpDecoder.decodeLine(in);
+        if (header == null) {
+            return false;
+        }
+
+        httpDecoder.decodeStatus(header, response);
+
+        return true;
+    }
+}

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpResponseDecoder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpResponseDecoder.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpResponseDecoder.java
------------------------------------------------------------------------------
    svn:mime-type = text/x-java

Added: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpResponseMessage.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpResponseMessage.java?rev=607542&view=auto
==============================================================================
--- geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpResponseMessage.java (added)
+++ geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpResponseMessage.java Sun Dec 30 03:36:47 2007
@@ -0,0 +1,245 @@
+/*
+ *  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.codec;
+
+import java.util.HashMap;
+import java.util.ArrayList;
+
+import org.apache.ahc.auth.AuthState;
+import org.apache.ahc.util.NameValuePair;
+
+/**
+ * The Class HttpResponseMessage. This is an object representation of an HTTP response.
+ */
+public class HttpResponseMessage extends HttpMessage {
+
+    /** The Constant EXPECTED_NOT_READ. */
+    static final int EXPECTED_NOT_READ = -1;
+
+    /** The Constant STATE_START. */
+    static final int STATE_START = 0;
+    
+    /** The Constant STATE_STATUS_CONTINUE. */
+    static final int STATE_STATUS_CONTINUE = 1;
+    
+    /** The Constant STATE_STATUS_READ. */
+    static final int STATE_STATUS_READ = 2;
+    
+    /** The Constant STATE_HEADERS_READ. */
+    static final int STATE_HEADERS_READ = 3;
+    
+    /** The Constant STATE_CONTENT_READ. */
+    static final int STATE_CONTENT_READ = 4;
+    
+    /** The Constant STATE_FOOTERS_READ. */
+    static final int STATE_FOOTERS_READ = 5;
+    
+    /** The Constant STATE_FINISHED. */
+    static final int STATE_FINISHED = 6;
+
+    /** The status code. */
+    private int statusCode;
+    
+    /** The status message. */
+    private String statusMessage;
+    
+    /** The connection. */
+    private String connection;
+
+    /** The chunked. */
+    private boolean chunked;
+    
+    /** The expected to read. */
+    private int expectedToRead = -1;
+    
+    /** The state. */
+    private int state = STATE_START;
+    
+    /** The location. */
+    private String location;
+
+    /** The attachment. */
+    private Object attachment;
+
+    /** The challenge list **/
+    private ArrayList<NameValuePair> challenges = new ArrayList<NameValuePair>();
+    
+    /**
+     * Gets the HTTP status code.
+     * 
+     * @return the HTTP status code
+     */
+    public int getStatusCode() {
+        return statusCode;
+    }
+
+    /**
+     * Sets the HTTP status code.
+     * 
+     * @param statusCode the new HTTP status code
+     */
+    public void setStatusCode(int statusCode) {
+        this.statusCode = statusCode;
+    }
+
+    /**
+     * Gets the HTTP status message.
+     * 
+     * @return the HTTP status message
+     */
+    public String getStatusMessage() {
+        return statusMessage;
+    }
+
+    /**
+     * Sets the HTTP status message.
+     * 
+     * @param statusMessage the new HTTP status message
+     */
+    public void setStatusMessage(String statusMessage) {
+        this.statusMessage = statusMessage;
+    }
+
+    /**
+     * Checks if the response is transcoded as chunked.
+     * 
+     * @return <code>true</code> if the transcoding is chunked
+     */
+    boolean isChunked() {
+        return chunked;
+    }
+
+    /**
+     * Flags the response transcoding chunked.
+     * 
+     * @param chunked <code>true</code> if the transcoding is chunked
+     */
+    void setChunked(boolean chunked) {
+        this.chunked = chunked;
+    }
+
+    /**
+     * Gets the expected number of bytes to read.  Used during decoding chunked transcoding.
+     * 
+     * @return the expected to read
+     */
+    int getExpectedToRead() {
+        return expectedToRead;
+    }
+
+    /**
+     * Sets the expected number of bytes to read. Used during decoding chunked transcoding.
+     * 
+     * @param expectedToRead the new expected number of bytes to read
+     */
+    void setExpectedToRead(int expectedToRead) {
+        this.expectedToRead = expectedToRead;
+    }
+
+    /**
+     * Gets the state of the response during decoding.
+     * 
+     * @return the state
+     */
+    int getState() {
+        return state;
+    }
+
+    /**
+     * Sets the state of the response during decoding.
+     * 
+     * @param state the new state
+     */
+    void setState(int state) {
+        this.state = state;
+    }
+
+    /**
+     * Gets the location that is typically set on redirects.
+     * 
+     * @return the location or <code>null</code> if one does not exist.
+     */
+    public String getLocation() {
+        return location;
+    }
+
+    /**
+     * Sets the location that is typically set on redirects.
+     * 
+     * @param location the new location
+     */
+    public void setLocation(String location) {
+        this.location = location;
+    }
+
+    /**
+     * Gets the <code>Connection</code> value from an HTTP header.
+     * 
+     * @return the connection
+     */
+    public String getConnection() {
+        return connection;
+    }
+
+    /**
+     * Sets the <code>Connection</code> value from an HTTP header.
+     * 
+     * @param connection the new connection
+     */
+    public void setConnection(String connection) {
+        this.connection = connection;
+    }
+
+
+    /**
+     * Gets the attachment.
+     * 
+     * @return the attachment
+     */
+    public Object getAttachment() {
+        return attachment;
+    }
+
+    /**
+     * Sets the attachment.
+     * 
+     * @param attachment the new attachment
+     */
+    public void setAttachment(Object attachment) {
+        this.attachment = attachment;
+    }
+
+        /**
+     * Gets the challenges map
+     * @return the challenges map.
+     */
+    public ArrayList<NameValuePair> getChallenges() {
+        return challenges;
+    }
+
+    /**
+     * Adds a challenge to the challenge list
+     *
+     * @param challenge the challenge name value pair
+     */
+    public void addChallenge(NameValuePair challenge){
+        challenges.add(challenge);
+    }
+}

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpResponseMessage.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpResponseMessage.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/HttpResponseMessage.java
------------------------------------------------------------------------------
    svn:mime-type = text/x-java

Added: geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/ResponseFuture.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/ResponseFuture.java?rev=607542&view=auto
==============================================================================
--- geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/ResponseFuture.java (added)
+++ geronimo/sandbox/async-http-client-mina2/src/main/java/org/apache/ahc/codec/ResponseFuture.java Sun Dec 30 03:36:47 2007
@@ -0,0 +1,129 @@
+/*
+ *  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.codec;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.ahc.AsyncHttpClientCallback;
+
+/**
+ * Future that wraps the response of an asynchronous HTTP request.  It simply
+ * extends FutureTask to borrow AQS.  This future transitions to <tt>done</tt> 
+ * through setting the result or the exception.  The instances are considered 
+ * one time objects; i.e. once completed, the instance may not be reused.
+ * <p>
+ * Also, cancellation through this future is not supported.
+ */
+public class ResponseFuture extends FutureTask<HttpResponseMessage> 
+        implements Future<HttpResponseMessage> {
+    // dummy instance because I use the FutureTask constructor
+    // is not really used...
+    private static final Callable<HttpResponseMessage> DUMMY = 
+            new Callable<HttpResponseMessage>() {
+                public HttpResponseMessage call() throws Exception {
+                    return null;
+                }
+    };
+    
+    private final HttpRequestMessage request;
+    private final BlockingQueue<ResponseFuture> queue;
+    private final AsyncHttpClientCallback callback;
+    
+    /**
+     * Constructor.  Optionally one can pass in the completion queue and/or the
+     * callback object.
+     * 
+     * @param queue optional completion queue.  If not null, this future will be
+     * placed in the queue on completion.
+     * @param callback optional callback object.  If not null, the callback will
+     * be invoked at proper stages on completion.
+     */
+    public ResponseFuture(HttpRequestMessage request, 
+            BlockingQueue<ResponseFuture> queue) {
+        super(DUMMY);
+        this.request = request;
+        this.queue = queue;
+        this.callback = request.getCallback();
+    }
+    
+    public HttpRequestMessage getRequest() {
+        return request;
+    }
+    
+    /**
+     * On completion, adds this future object to the completion queue if it is 
+     * not null.
+     */
+    @Override
+    protected void done() {
+        // add itself to the blocking queue so clients can pick it up
+        if (queue != null) {
+            queue.add(this);
+        }
+    }
+
+    /**
+     * Sets the response and completes the future.  If a non-null callback was
+     * provided, the callback will be invoked 
+     * (<tt>AsyncHttpClientCallback.onResponse()</tt>) on the thread on which
+     * this method is invoked.
+     */
+    @Override
+    public void set(HttpResponseMessage v) {
+        super.set(v);
+        // fire the callback once the future is done
+        if (callback != null) {
+            callback.onResponse(v);
+        }
+    }
+
+    /**
+     * Sets the exception and completes the future.  If a non-null callback was
+     * provided, the callback will be invoked 
+     * (<tt>AsyncHttpClientCallback.onException()</tt> or 
+     * <tt>AsyncHttpClientCallback.onTimeout()</tt>) on the thread on which
+     * this method is invoked.
+     */
+    @Override
+    public void setException(Throwable t) {
+        super.setException(t);
+        // fire the callback once the future is done
+        if (callback != null) {
+            if (t instanceof TimeoutException) {
+                callback.onTimeout();
+            } else {
+                callback.onException(t);
+            }
+        }
+    }
+    
+    /**
+     * Canceling via this method is not allowed.  An 
+     * UnsupportedOperationException will be thrown.
+     */
+    @Override
+    public boolean cancel(boolean mayInterruptIfRunning) {
+        throw new UnsupportedOperationException("we don't support canceling asynchronous HTTP request via this method...");
+    }
+}



Mime
View raw message