Source code for /engineering/autohit-1998/autohit/transport/HTTPTransport.javaOriginal file HTTPTransport.java
   1 /**
   2  * .
   3  * Copyright � 1999 Erich P G.
   4  *
   5  */
   6  
   7 package autohit.transport;
   8 
   9 import HTTPClient.HTTPConnection;
  10 import HTTPClient.HTTPResponse;
  11 import HTTPClient.CookiePolicyHandler;
  12 import HTTPClient.CookieModule;
  13 import HTTPClient.Cookie;
  14 import HTTPClient.RoRequest;
  15 import HTTPClient.RoResponse;
  16 
  17 /**
  18  *  A HTTP transport.  It uses the HTTPClient library.  for http implementation specifics, 
  19  *  see the library documentation.
  20  *  <p>
  21  *  I'm thinking that HTTPClient will have to get replaced.  It will be slow.  It
  22  *  works for multi-client simulation, but it isn't designed for it.  I'm worried
  23  *  that Objects and cookies will ghost and build up.
  24  *  <p>
  25  * @author Erich P. Gatejen
  26  * @version 1.0
  27  * <i>Version History</i>
  28  * <code>EPG - Initial - 18Jan99</code> 
  29  * 
  30  */
  31 public class HTTPTransport implements Transport, CookiePolicyHandler {
  32 	
  33 	// --- FINAL FIELDS ------------------------------------------------------	
  34 
  35 	// --- FIELDS ------------------------------------------------------------
  36 
  37     /**
  38      *  Address.
  39      */ 
  40     private String  addr;
  41 
  42     /**
  43      *  Port.
  44      */ 
  45     private int     port;
  46     
  47     /**
  48      *  HTTP Connection.
  49      */ 
  50     private HTTPConnection  con;
  51   
  52     /*
  53      *  Allow cookies?
  54      */ 
  55     private boolean cookies     = true;
  56     
  57 
  58 	// --- PUBLIC METHODS ----------------------------------------------------
  59 	
  60     /**
  61      *  Default constructor.
  62      */
  63     public HTTPTransport() {
  64         
  65         con = null;        
  66     }
  67      
  68     /**
  69      *  Prepare to connect to a web server.  If this method is subsiquently
  70      *  called BEFORE the connection is disconnect()'ed, it will throw a TransportException.
  71      * 
  72      *  The port can be specified in the address--such as "my.domain.com:8080"
  73      *
  74      *  @param address Address specification.  This should only be the DOMAIN portion
  75      *                 of a URL.
  76      *
  77      *  @throws autohit.transport.TransportException     
  78      */     
  79     public void connect(String  address) throws TransportException {
  80         
  81         if (con != null) throw new TransportException("Already connected.");
  82 
  83         try {
  84             // is there a port or not?
  85             int c = address.indexOf(":");
  86             if (c >= 0) {
  87                 addr = address.substring(0, c-1);
  88                 String portText = address.substring(c+1, address.length()-1 );
  89                 port = Integer.parseInt(portText);
  90                 
  91             } else {
  92                 addr = address;
  93                 port = 80;           
  94             }
  95             
  96         } catch (Exception e) {  throw new TransportException("Bad address string."); }
  97         
  98         con = new HTTPConnection(addr, port);
  99         con.setContext(this);                   // We want to be autonomous.
 100         CookieModule.setCookiePolicyHandler(this);  // move this? 
 101     }
 102 
 103     /**
 104      *  Push a query and <b>wait</b> for a response.
 105      *  <p>  
 106      *  <pre>
 107      *  The Query should be formed as the following:
 108      *      Query.headers = any non-default headers.  Be careful that they they
 109      *                      don't break how HTTPClient works.
 110      *      Query.qs      = The URI query string including URL encoded variables.
 111      *                      It should include the "/" after the domain in URI--such
 112      *                      as "/cgi-bin/goats.pl" rather than "cgi-bin/goats.pl"
 113      *      Query.body    = Any body elements.  If this is null, then the http GET method
 114      *                      will be used.  Otherwise, http POST is used and this body will
 115      *                      be the form data.
 116      *  </pre>
 117      *  <p>
 118      *  WARNING!  For now, headers are not given in the Response.  Reponse.header
 119      *  will be null.
 120      *  <p>
 121      *  If it is not connected or there is an underlying transport error, it will 
 122      *  throw a TransportException.
 123      *
 124      *  @param q A queury specification.
 125      *  @return A response object.
 126      *  @throws autohit.transport.TransportException
 127      *  @see autohit.transport.Query
 128      *  @see autohit.transport.Response
 129      */   
 130     public Response push(Query  q) throws TransportException {
 131 
 132         if (addr == null) throw new TransportException("Not connected.");
 133 
 134         HTTPResponse    rep;
 135         Response        r; 
 136  
 137         try {
 138 
 139             if (q.body == null) {
 140             
 141                 // USE GET
 142                 rep = con.Get(q.qs, "", q.headers);
 143             
 144             } else {     
 145                       
 146                 // USE POST
 147                 rep = con.Post(q.qs, q.body, q.headers);
 148                        
 149             }
 150         } catch (Exception e) {
 151             throw new TransportException("Failed Query [" + addr + ":" + port + q.qs + "] with JAVA Exception: " + e.getMessage() );
 152         }
 153 
 154         try {        
 155             r = new Response();
 156             r.headers  = null;
 157             r.code     = rep.getStatusCode();
 158             r.content  = rep.getData();
 159             r.cLength  = r.content.length;
 160         } catch (Exception e) {
 161             throw new TransportException("Failed Response [" + addr + ":" + port + q.qs + "] with JAVA Exception: " + e.getMessage() );
 162         }
 163 
 164         return r;
 165     }
 166 
 167     /**
 168      *  Set an environment variable for this transport.
 169      *  <p><pre>
 170      *  The following as defined for this transport.  (Defaults shown in paren.)
 171      *
 172      *      - Accept cookies?   "cookies" == "true" or "false" (true)
 173      *      - Allow redirects?  "redir" == "true" or "false" (true)
 174      *                          WARNING!  For now, redirects will ALWAYS be allowed.
 175      *                          I'll have to hack the HTTPClient to change this....
 176      *  </pre><p>
 177      *  Names and boolean values are NOT case sensitive.
 178      *  
 179      *  @param name variable name.
 180      *  @param value variable value.
 181      */ 
 182     public void environment(String  name, String  value) {
 183 
 184         if (name.compareToIgnoreCase("cookies") == 0) {
 185             
 186             if (value.compareToIgnoreCase("true") == 0) cookies = true;
 187             else cookies = false;           
 188             
 189         } //else if (name.compareToIgnoreCase("redir") == 0) {
 190         
 191         //}
 192     }
 193 
 194     /**
 195      *  Disconnect transport.
 196      *  <p>
 197      *  If it isn't currently connected, nothing bad will happen.
 198      */
 199     public void disconnect() {
 200         
 201         // Null this reference.  Hopefully GC will get to it soon.  :D
 202         // ...  erk, I also hope the cookies all go away when there are no
 203         // more active HTTPConnection's.
 204         con = null;            
 205     }
 206  
 207 	// --- COOKIE INTERFACE ---------------------------------------------------
 208 
 209     /**
 210      *  Just don't use these...  We will use the environemnt var to decide whether
 211      *  to allow cookies....
 212      */       
 213     public boolean acceptCookie(Cookie      cookie,
 214                                 RoRequest   req,
 215                                 RoResponse  resp) {
 216         return cookies;                                    
 217                                         
 218     }
 219     public boolean sendCookie(Cookie cookie, RoRequest req) {
 220                                     
 221         return cookies;
 222     }                                
 223                                     
 224     
 225  
 226 	// --- PRIVATE METHODS ---------------------------------------------------	
 227 }