001 /* 002 The contents of this file are subject to the Mozilla Public License Version 1.1 003 (the "License"); you may not use this file except in compliance with the License. 004 You may obtain a copy of the License at http://www.mozilla.org/MPL/ 005 Software distributed under the License is distributed on an "AS IS" basis, 006 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the 007 specific language governing rights and limitations under the License. 008 009 The Original Code is "URLTransport.java". Description: 010 "A TransportLayer that reads and writes from an URL." 011 012 The Initial Developer of the Original Code is University Health Network. Copyright (C) 013 2004. All Rights Reserved. 014 015 Contributor(s): ______________________________________. 016 017 Alternatively, the contents of this file may be used under the terms of the 018 GNU General Public License (the ?GPL?), in which case the provisions of the GPL are 019 applicable instead of those above. If you wish to allow use of your version of this 020 file only under the terms of the GPL and not to allow others to use your version 021 of this file under the MPL, indicate your decision by deleting the provisions above 022 and replace them with the notice and other provisions required by the GPL License. 023 If you do not delete the provisions above, a recipient may use your version of 024 this file under either the MPL or the GPL. 025 */ 026 027 package ca.uhn.hl7v2.protocol.impl; 028 029 import java.io.BufferedInputStream; 030 import java.io.BufferedOutputStream; 031 import java.io.IOException; 032 import java.io.InputStreamReader; 033 import java.io.OutputStreamWriter; 034 import java.io.Reader; 035 import java.io.Writer; 036 import java.net.URL; 037 import java.net.URLConnection; 038 039 import ca.uhn.hl7v2.protocol.TransportException; 040 import ca.uhn.hl7v2.protocol.TransportLayer; 041 import ca.uhn.hl7v2.protocol.Transportable; 042 import ca.uhn.log.HapiLog; 043 import ca.uhn.log.HapiLogFactory; 044 045 /** 046 * A <code>TransportLayer</code> that reads and writes from an URL (for example 047 * over HTTP). 048 * 049 * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a> 050 * @author <a href="mailto:alexei.guevara@uhn.on.ca">Alexei Guevara</a> 051 * @version $Revision: 1.1 $ updated on $Date: 2007/02/19 02:24:26 $ by $Author: jamesagnew $ 052 */ 053 public class URLTransport extends AbstractTransport implements TransportLayer { 054 055 private static final HapiLog log = HapiLogFactory.getHapiLog(URLTransport.class); 056 057 /** 058 * Key in Transportable metadata map under which URL is stored. 059 */ 060 public static final String URL_KEY = "URL"; 061 062 private String myContentType = "application/hl7+doc+xml"; 063 private URL myURL; 064 private URLConnection myConnection; 065 protected int myBufferSize = 3000; 066 067 private final boolean myConnectOnSend; 068 private final boolean myConnectOnReceive; 069 private final boolean myConnectOnConnect; 070 071 /** 072 * The boolean configuration flags determine when new connections are made. For example if this 073 * transport is being used for query/response, you might set connectOnSend to true and 074 * the others to false, so that each query/response is done over a fresh connection. If 075 * you are using a transport just to read data from a URL, you might set connectOnReceive to 076 * true and the others to false. 077 * 078 * @param theURL the URL at which messages are to be read and written 079 * @param connectOnSend makes a new connection before each send 080 * @param connectOnReceive makes a new connection before each receive 081 * @param connectOnConnect makes a new connection when connect() is called 082 */ 083 public URLTransport(URL theURL, boolean connectOnSend, boolean connectOnReceive, boolean connectOnConnect) { 084 myURL = theURL; 085 getCommonMetadata().put(URL_KEY, theURL); 086 087 myConnectOnSend = connectOnSend; 088 myConnectOnReceive = connectOnReceive; 089 myConnectOnConnect = connectOnConnect; 090 } 091 092 /** 093 * Writes the given message to the URL. 094 * 095 * @param theMessage the message to send 096 * @see ca.uhn.hl7v2.protocol.AbstractTransport#doSend(ca.uhn.hl7v2.protocol.Transportable) 097 */ 098 public void doSend(Transportable theMessage) throws TransportException { 099 if (myConnectOnSend) { 100 makeConnection(); 101 } 102 103 try { 104 Writer out = new OutputStreamWriter(new BufferedOutputStream(myConnection.getOutputStream())); 105 out.write(theMessage.getMessage()); 106 out.flush(); 107 } catch (IOException e) { 108 throw new TransportException(e); 109 } 110 } 111 112 /** 113 * @see ca.uhn.hl7v2.protocol.AbstractTransport#doReceive() 114 */ 115 public Transportable doReceive() throws TransportException { 116 117 if (myConnectOnReceive) { 118 makeConnection(); 119 } 120 121 StringBuffer response = new StringBuffer(); 122 123 try { 124 log.debug("Getting InputStream from URLConnection"); 125 Reader in = new InputStreamReader(new BufferedInputStream(myConnection.getInputStream())); 126 log.debug("Got InputStream from URLConnection"); 127 128 char[] buf = new char[myBufferSize]; 129 int bytesRead = 0; 130 131 int tryToReadCount = 0; 132 133 IntRef bytesReadRef = new IntRef(); 134 135 while (bytesRead >= 0) { 136 137 try { 138 ReaderThread readerThread = new ReaderThread(in, buf, bytesReadRef); 139 readerThread.start(); 140 readerThread.join(10000); 141 142 bytesRead = bytesReadRef.getValue(); 143 144 if (bytesRead == 0) { 145 throw new TransportException("Timeout waiting for response"); 146 } 147 } 148 catch (InterruptedException x) { 149 } 150 151 if (bytesRead > 0) { 152 response.append(buf, 0, bytesRead); 153 } 154 155 } 156 157 in.close(); 158 } catch (IOException e) { 159 log.error(e); 160 } 161 162 if (response.length() == 0) { 163 throw new TransportException("Timeout waiting for response"); 164 } 165 166 return new TransportableImpl(response.toString()); 167 } 168 169 170 /** 171 * Calls openConnection() on the underlying URL and configures the connection, 172 * if this transport is configured to connect when connect() is called (see 173 * constructor params). 174 * 175 * @see ca.uhn.hl7v2.protocol.AbstractTransport#doConnect() 176 */ 177 public void doConnect() throws TransportException { 178 if (myConnectOnConnect) { 179 makeConnection(); 180 } 181 } 182 183 //makes new connection 184 private void makeConnection() throws TransportException { 185 try { 186 myConnection = myURL.openConnection(); 187 myConnection.setDoOutput(true); 188 myConnection.setDoInput(true); 189 myConnection.setRequestProperty("Content-Type", getContentType()); 190 myConnection.connect(); 191 } catch (IOException e) { 192 throw new TransportException(e); 193 } 194 log.debug("Made connection to " + myURL.toExternalForm()); 195 } 196 197 /** 198 * @return the string used in the request property "Content-Type" (defaults to 199 * "application/hl7+doc+xml") 200 */ 201 public String getContentType() { 202 return myContentType; 203 } 204 205 /** 206 * @param theContentType the string to be used in the request property "Content-Type" 207 * (defaults to "application/hl7+doc+xml") 208 */ 209 public void setContentType(String theContentType) { 210 myContentType = theContentType; 211 } 212 213 /** 214 * @see ca.uhn.hl7v2.protocol.TransportLayer#disconnect() 215 */ 216 public void doDisconnect() throws TransportException { 217 myConnection = null; 218 } 219 220 }