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 }