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 final URL myURL;
65      private URLConnection myConnection;
66      protected final 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       */
98      public void doSend(Transportable theMessage) throws TransportException {
99          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     public Transportable doReceive() throws TransportException {
113         
114         if (myConnectOnReceive) {
115             makeConnection();
116         }
117 
118         StringBuilder response = new StringBuilder();
119 
120         try {
121             log.debug("Getting InputStream from URLConnection");
122             Reader in = new InputStreamReader(new BufferedInputStream(myConnection.getInputStream()));
123             log.debug("Got InputStream from URLConnection");
124 
125             char[] buf = new char[myBufferSize];
126             int bytesRead = 0;
127 
128             IntRefef.html#IntRef">IntRef bytesReadRef = new IntRef();
129 
130             while (bytesRead >= 0) {
131 
132                 try {
133                     ReaderThreadad.html#ReaderThread">ReaderThread readerThread = new ReaderThread(in, buf, bytesReadRef);
134                     readerThread.start();
135                     readerThread.join(10000);
136 
137                     bytesRead = bytesReadRef.getValue();
138 
139                     if (bytesRead == 0) {
140                         throw new TransportException("Timeout waiting for response");
141                     }
142                 }
143                 catch (InterruptedException ignored) {
144                 }
145 
146                 if (bytesRead > 0) {
147                     response.append(buf, 0, bytesRead);
148                 }
149 
150             }
151 
152             in.close();
153         } catch (IOException e) {
154             log.error(e.getMessage(), e);
155         }
156 
157         if (response.length() == 0) {
158             throw new TransportException("Timeout waiting for response");
159         }
160 
161         return new TransportableImpl(response.toString());
162     }
163 
164 
165     /** 
166      * Calls openConnection() on the underlying URL and configures the connection, 
167      * if this transport is configured to connect when connect() is called (see 
168      * constructor params).
169      */
170     public void doConnect() throws TransportException {
171         if (myConnectOnConnect) {
172             makeConnection();
173         }
174     }
175     
176     //makes new connection 
177     private void makeConnection() throws TransportException {
178         try {
179             myConnection = myURL.openConnection();
180             myConnection.setDoOutput(true);
181             myConnection.setDoInput(true);
182             myConnection.setRequestProperty("Content-Type", getContentType());
183             myConnection.connect();
184         } catch (IOException e) {
185             throw new TransportException(e);
186         }     
187         log.debug("Made connection to {}", myURL.toExternalForm());
188     }
189     
190     /**
191      * @return the string used in the request property "Content-Type" (defaults to 
192      *      "application/hl7+doc+xml")
193      */
194     public String getContentType() {
195         return myContentType;
196     }
197     
198     /**
199      * @param theContentType the string to be used in the request property "Content-Type" 
200      *      (defaults to "application/hl7+doc+xml")
201      */
202     public void setContentType(String theContentType) {
203         myContentType = theContentType;
204     }
205 
206     /** 
207      * @see ca.uhn.hl7v2.protocol.TransportLayer#disconnect()
208      */
209     public void doDisconnect() {
210         myConnection = null;
211     }
212     
213 }