001    /*
002    Copyright (c) 2003, The Regents of the University of California, through
003    Lawrence Berkeley National Laboratory (subject to receipt of any required
004    approvals from the U.S. Dept. of Energy).  All rights reserved.
005    */
006    package gov.lbl.dsd.sea.demo;
007    
008    import gov.lbl.dsd.sea.EventHandler;
009    import gov.lbl.dsd.sea.Stage;
010    import gov.lbl.dsd.sea.event.ExceptionEvent;
011    import gov.lbl.dsd.sea.event.IllegalEventException;
012    
013    import java.io.IOException;
014    
015    import org.apache.commons.httpclient.HttpClient;
016    import org.apache.commons.httpclient.HttpMethod;
017    import org.apache.commons.httpclient.HttpRecoverableException;
018    import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
019    //import org.apache.commons.httpclient.SimpleHttpConnectionManager;
020    
021    /**
022     * Simple HTTP 1.1 handler with limited functionality;
023     * Internally uses the raw commons-httpclient library.
024     *
025     * @author whoschek@lbl.gov
026     * @author $Author: hoschek3 $
027     * @version $Revision: 1.1 $, $Date: 2004/05/29 19:24:57 $
028     */
029    public class SimpleHTTPEventHandler extends EventHandler {
030    
031            protected HttpClient client;
032            protected Stage sink;
033    
034            private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(SimpleHTTPEventHandler.class);
035    
036            /** Creates a handler that enqueues HTTP responses onto the given sink
037             *
038             * @param sink the sink to enqueue responses onto
039             */
040            public SimpleHTTPEventHandler(Stage sink)  {
041                    this(sink, createHttpClient());
042            }
043    
044            public SimpleHTTPEventHandler(Stage sink, HttpClient client)  {
045                    this.sink = sink;
046                    this.client = client;
047            }
048    
049            public void handle(Object object) {
050                    if (object instanceof HttpMethod) {
051                            HttpMethod method = (HttpMethod) object;
052    
053                            Object rsp = null;
054                            try {
055                                    int statusCode = this.executeMethod(method);
056                                    byte[] body = method.getResponseBody();
057                                    rsp = new ByteArrayEvent(this.getStage(), body, new Integer(statusCode));
058                            } catch (IOException exc) {
059                                    rsp = new ExceptionEvent(exc, object, this.getStage());
060                            }
061                            finally {
062                                    method.releaseConnection();
063                            }
064                            this.sink.enqueue(rsp);
065                    }
066                    else {
067                            throw new IllegalEventException(object, this.getStage());
068                            //this.sink.enqueue(new IllegalEventException(event, this.getStage()));
069                    }
070            }
071    
072            protected int executeMethod(HttpMethod method) throws IOException {
073                    int attempts = 3; // We will retry up to 3 times.
074                    int statusCode = -1;
075                    while (statusCode == -1 && attempts-- > 0) {
076                            try {
077                                    statusCode = this.client.executeMethod(method); // execute the method.
078                            } catch (HttpRecoverableException e) {
079                                    log.warn("A recoverable HTTP exception occurred, retrying: ", e);
080                                    if (attempts <= 0) throw e; // rethrow
081                            }
082                    }
083    
084                    return statusCode;
085            }
086    
087            protected static HttpClient createHttpClient() {
088                    //SimpleHttpConnectionManager connectionMgr = new SimpleHttpConnectionManager();
089                    MultiThreadedHttpConnectionManager connectionMgr = new MultiThreadedHttpConnectionManager();
090    
091                    connectionMgr.setConnectionStaleCheckingEnabled(false); // improves performance by a factor of 50!
092                    return new HttpClient(connectionMgr);
093            }
094    }