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 }