View Javadoc

1   /*
2   The contents of this file are subject to the Mozilla Public License Version 1.1 
3   (the "License"); you may not use this file except in compliance with the License. 
4   You may obtain a copy of the License at http://www.mozilla.org/MPL/ 
5   Software distributed under the License is distributed on an "AS IS" basis, 
6   WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the 
7   specific language governing rights and limitations under the License. 
8   
9   The Original Code is "URLTransport.java".  Description: 
10  "A TransportLayer that reads and writes from an URL." 
11  
12  The Initial Developer of the Original Code is University Health Network. Copyright (C) 
13  2004.  All Rights Reserved. 
14  
15  Contributor(s): ______________________________________. 
16  
17  Alternatively, the contents of this file may be used under the terms of the 
18  GNU General Public License (the "GPL"), in which case the provisions of the GPL are 
19  applicable instead of those above.  If you wish to allow use of your version of this 
20  file only under the terms of the GPL and not to allow others to use your version 
21  of this file under the MPL, indicate your decision by deleting  the provisions above 
22  and replace  them with the notice and other provisions required by the GPL License.  
23  If you do not delete the provisions above, a recipient may use your version of 
24  this file under either the MPL or the GPL. 
25  */
26  
27  package ca.uhn.hl7v2.protocol.impl;
28  
29  import java.io.BufferedInputStream;
30  import java.io.BufferedOutputStream;
31  import java.io.IOException;
32  import java.io.InputStreamReader;
33  import java.io.OutputStreamWriter;
34  import java.io.Reader;
35  import java.io.Writer;
36  import java.net.URL;
37  import java.net.URLConnection;
38  
39  import org.slf4j.Logger;
40  import org.slf4j.LoggerFactory;
41  
42  import ca.uhn.hl7v2.protocol.TransportException;
43  import ca.uhn.hl7v2.protocol.TransportLayer;
44  import ca.uhn.hl7v2.protocol.Transportable;
45  
46  /**
47   * A <code>TransportLayer</code> that reads and writes from an URL (for example
48   * over HTTP).    
49   * 
50   * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a>
51   * @author <a href="mailto:alexei.guevara@uhn.on.ca">Alexei Guevara</a>
52   * @version $Revision: 1.1 $ updated on $Date: 2007-02-19 02:24:26 $ by $Author: jamesagnew $
53   */
54  public class URLTransport extends AbstractTransport implements TransportLayer {
55      
56      private static final Logger log = LoggerFactory.getLogger(URLTransport.class);    
57  
58      /**
59       * Key in Transportable metadata map under which URL is stored.  
60       */
61      public static final String URL_KEY = "URL";
62  
63      private String myContentType = "application/hl7+doc+xml";
64      private URL myURL;
65      private URLConnection myConnection;
66      protected int myBufferSize = 3000;
67      
68      private final boolean myConnectOnSend;
69      private final boolean myConnectOnReceive;
70      private final boolean myConnectOnConnect;
71  
72      /**
73       * The boolean configuration flags determine when new connections are made.  For example if this 
74       * transport is being used for query/response, you might set connectOnSend to true and
75       * the others to false, so that each query/response is done over a fresh connection.  If 
76       * you are using a transport just to read data from a URL, you might set connectOnReceive to 
77       * true and the others to false.  
78       *  
79       * @param theURL the URL at which messages are to be read and written 
80       * @param connectOnSend makes a new connection before each send  
81       * @param connectOnReceive makes a new connection before each receive 
82       * @param connectOnConnect makes a new connection when connect() is called 
83       */
84      public URLTransport(URL theURL, boolean connectOnSend, boolean connectOnReceive, boolean connectOnConnect) {
85          myURL = theURL;
86          getCommonMetadata().put(URL_KEY, theURL);
87          
88          myConnectOnSend = connectOnSend;
89          myConnectOnReceive = connectOnReceive;
90          myConnectOnConnect = connectOnConnect;
91      }
92  
93      /** 
94       * Writes the given message to the URL. 
95       * 
96       * @param theMessage the message to send 
97       * @see ca.uhn.hl7v2.protocol.AbstractTransport#doSend(ca.uhn.hl7v2.protocol.Transportable)
98       */
99      public void doSend(Transportable theMessage) throws TransportException {
100         if (myConnectOnSend) {
101             makeConnection();
102         }
103 
104         try {
105             Writer out = new OutputStreamWriter(new BufferedOutputStream(myConnection.getOutputStream()));
106             out.write(theMessage.getMessage());
107             out.flush();
108         } catch (IOException e) {
109             throw new TransportException(e);
110         }
111     }
112 
113     /**
114      * @see ca.uhn.hl7v2.protocol.AbstractTransport#doReceive()
115      */
116     public Transportable doReceive() throws TransportException {
117         
118         if (myConnectOnReceive) {
119             makeConnection();
120         }
121 
122         StringBuffer response = new StringBuffer();
123 
124         try {
125             log.debug("Getting InputStream from URLConnection");
126             Reader in = new InputStreamReader(new BufferedInputStream(myConnection.getInputStream()));
127             log.debug("Got InputStream from URLConnection");
128 
129             char[] buf = new char[myBufferSize];
130             int bytesRead = 0;
131 
132             IntRef bytesReadRef = new IntRef();
133 
134             while (bytesRead >= 0) {
135 
136                 try {
137                     ReaderThread readerThread = new ReaderThread(in, buf, bytesReadRef);
138                     readerThread.start();
139                     readerThread.join(10000);
140 
141                     bytesRead = bytesReadRef.getValue();
142 
143                     if (bytesRead == 0) {
144                         throw new TransportException("Timeout waiting for response");
145                     }
146                 }
147                 catch (InterruptedException x) {
148                 }
149 
150                 if (bytesRead > 0) {
151                     response.append(buf, 0, bytesRead);
152                 }
153 
154             }
155 
156             in.close();
157         } catch (IOException e) {
158             log.error(e.getMessage(), e);
159         }
160 
161         if (response.length() == 0) {
162             throw new TransportException("Timeout waiting for response");
163         }
164 
165         return new TransportableImpl(response.toString());
166     }
167 
168 
169     /** 
170      * Calls openConnection() on the underlying URL and configures the connection, 
171      * if this transport is configured to connect when connect() is called (see 
172      * constructor params).
173      *   
174      * @see ca.uhn.hl7v2.protocol.AbstractTransport#doConnect()
175      */
176     public void doConnect() throws TransportException {
177         if (myConnectOnConnect) {
178             makeConnection();
179         }
180     }
181     
182     //makes new connection 
183     private void makeConnection() throws TransportException {
184         try {
185             myConnection = myURL.openConnection();
186             myConnection.setDoOutput(true);
187             myConnection.setDoInput(true);
188             myConnection.setRequestProperty("Content-Type", getContentType());
189             myConnection.connect();
190         } catch (IOException e) {
191             throw new TransportException(e);
192         }     
193         log.debug("Made connection to {}", myURL.toExternalForm());
194     }
195     
196     /**
197      * @return the string used in the request property "Content-Type" (defaults to 
198      *      "application/hl7+doc+xml")
199      */
200     public String getContentType() {
201         return myContentType;
202     }
203     
204     /**
205      * @param theContentType the string to be used in the request property "Content-Type" 
206      *      (defaults to "application/hl7+doc+xml")
207      */
208     public void setContentType(String theContentType) {
209         myContentType = theContentType;
210     }
211 
212     /** 
213      * @see ca.uhn.hl7v2.protocol.TransportLayer#disconnect()
214      */
215     public void doDisconnect() throws TransportException {
216         myConnection = null;
217     }
218     
219 }