View Javadoc

1   package ca.uhn.hl7v2.hoh.encoder;
2   
3   import static org.junit.Assert.*;
4   
5   import java.io.ByteArrayInputStream;
6   import java.io.ByteArrayOutputStream;
7   import java.nio.charset.Charset;
8   
9   import org.junit.BeforeClass;
10  import org.junit.Test;
11  
12  import ca.uhn.hl7v2.hoh.encoder.AbstractHl7OverHttpDecoder;
13  import ca.uhn.hl7v2.hoh.encoder.Hl7OverHttpRequestDecoder;
14  import ca.uhn.hl7v2.hoh.util.GZipUtils;
15  import ca.uhn.hl7v2.hoh.util.SplitInputStream;
16  
17  public class Hl7OverHttpDecoderTest {
18  
19  	private static String ourSampleMessage;
20  	private static String ourSampleMessageWithMultibyte;
21  
22  	@BeforeClass
23  	public static void beforeClass() {
24  		ourSampleMessage = "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + 
25  				"EVN||200803051509\r" + 
26  				"PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r";
27  
28  		ourSampleMessageWithMultibyte = ourSampleMessage.replace("SSN", "Iā™„HAPI");
29  	}
30  
31  	// TODO: add test to make sure that a request with chunked encoding can be decoded
32  	
33  	@Test
34  	public void testDecodeFromStream() throws Exception {
35  
36  		ByteArrayOutputStream bos = new ByteArrayOutputStream();
37  		String msg = "POST /AppName HTTP/1.1\r\n" + "Content-Type: application/hl7-v2; charset=ISO-8859-2\r\n" + "Content-Length: " + ourSampleMessage.getBytes("ISO-8859-1").length + "\r\n" + "Authorization: Basic aGVsbG86d29ybGQ=\r\n" + "\r\n";
38  		bos.write(msg.getBytes("ISO-8859-1"));
39  		bos.write(ourSampleMessage.getBytes("ISO-8859-2"));
40  		AbstractHl7OverHttpDecoder d = new Hl7OverHttpRequestDecoder();
41  		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bos.toByteArray());
42  		d.readHeadersAndContentsFromInputStreamAndDecode(byteArrayInputStream);
43  
44  		assertEquals(0, byteArrayInputStream.available());
45  		assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty());
46  		assertEquals(Charset.forName("ISO-8859-2"), d.getCharset());
47  		assertTrue(d.isCharsetExplicitlySet());
48  		assertEquals("application/hl7-v2", d.getContentType());
49  		assertEquals(ourSampleMessage, d.getMessage());
50  		assertEquals("hello", d.getUsername());
51  		assertEquals("world", d.getPassword());
52  		assertEquals("/AppName", d.getPath());
53  
54  	}
55  
56  	/**
57  	 * Allow malformed client to be processed correctly, per
58  	 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.3
59  	 */
60  	@Test
61  	public void testDecodeFromStreamWithHeaderLineEndingLF() throws Exception {
62  
63  		ByteArrayOutputStream bos = new ByteArrayOutputStream();
64  		String msg = "POST /AppName HTTP/1.1\n" + // -
65  				"Content-Type: application/hl7-v2; charset=ISO-8859-2\n" + // -
66  				"Content-Length: " + ourSampleMessage.getBytes("ISO-8859-1").length + "\n" + // -
67  				"Authorization: Basic aGVsbG86d29ybGQ=\n" + // -
68  				"\n";
69  		bos.write(msg.getBytes("ISO-8859-1"));
70  		bos.write(ourSampleMessage.getBytes("ISO-8859-2"));
71  		AbstractHl7OverHttpDecoder d = new Hl7OverHttpRequestDecoder();
72  		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bos.toByteArray());
73  		d.readHeadersAndContentsFromInputStreamAndDecode(byteArrayInputStream);
74  
75  		assertEquals(0, byteArrayInputStream.available());
76  		assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty());
77  		assertEquals(Charset.forName("ISO-8859-2"), d.getCharset());
78  		assertTrue(d.isCharsetExplicitlySet());
79  		assertEquals("application/hl7-v2", d.getContentType());
80  		assertEquals(ourSampleMessage, d.getMessage());
81  		assertEquals("hello", d.getUsername());
82  		assertEquals("world", d.getPassword());
83  		assertEquals("/AppName", d.getPath());
84  
85  	}
86  
87  	/**
88  	 * Allow malformed client to be processed correctly, per
89  	 * http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.3
90  	 */
91  	@Test
92  	public void testDecodeFromStreamWithWeirdHeaderLineSpaces() throws Exception {
93  
94  		ByteArrayOutputStream bos = new ByteArrayOutputStream();
95  		String msg = "POST  \t\t /AppName         \tHTTP/1.1\n" + // -
96  				"Content-Type:\t\t application/hl7-v2; charset=ISO-8859-2\n" + // -
97  				"Content-Length:            " + ourSampleMessage.getBytes("ISO-8859-1").length + "\n" + // -
98  				"Authorization:\t\t\t\t Basic aGVsbG86d29ybGQ=\n" + // -
99  				"\n";
100 		bos.write(msg.getBytes("ISO-8859-1"));
101 		bos.write(ourSampleMessage.getBytes("ISO-8859-2"));
102 		AbstractHl7OverHttpDecoder d = new Hl7OverHttpRequestDecoder();
103 		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bos.toByteArray());
104 		d.readHeadersAndContentsFromInputStreamAndDecode(byteArrayInputStream);
105 
106 		assertEquals(0, byteArrayInputStream.available());
107 		assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty());
108 		assertEquals(Charset.forName("ISO-8859-2"), d.getCharset());
109 		assertTrue(d.isCharsetExplicitlySet());
110 		assertEquals("application/hl7-v2", d.getContentType());
111 		assertEquals(ourSampleMessage, d.getMessage());
112 		assertEquals("hello", d.getUsername());
113 		assertEquals("world", d.getPassword());
114 		assertEquals("/AppName", d.getPath());
115 
116 	}
117 
118 	@Test
119 	public void testDecodeFromStreamWithTwoMessages() throws Exception {
120 
121 		ByteArrayOutputStream bos = new ByteArrayOutputStream();
122 		String msg = "POST /AppName HTTP/1.1\r\n" + "Content-Type: application/hl7-v2; charset=ISO-8859-2\r\n" + "Content-Length: " + ourSampleMessage.getBytes("ISO-8859-1").length + "\r\n" + "Authorization: Basic aGVsbG86d29ybGQ=\r\n" + "\r\n";
123 		bos.write(msg.getBytes("ISO-8859-1"));
124 		bos.write(ourSampleMessage.getBytes("ISO-8859-2"));
125 
126 		// Double the message
127 		bos.write(bos.toByteArray());
128 
129 		AbstractHl7OverHttpDecoder d = new Hl7OverHttpRequestDecoder();
130 		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bos.toByteArray());
131 		d.readHeadersAndContentsFromInputStreamAndDecode(byteArrayInputStream);
132 
133 		assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty());
134 		assertEquals(Charset.forName("ISO-8859-2"), d.getCharset());
135 		assertTrue(d.isCharsetExplicitlySet());
136 		assertEquals("application/hl7-v2", d.getContentType());
137 		assertEquals(ourSampleMessage, d.getMessage());
138 		assertEquals("hello", d.getUsername());
139 		assertEquals("world", d.getPassword());
140 		assertEquals("/AppName", d.getPath());
141 
142 		// Read a second
143 
144 		d = new Hl7OverHttpRequestDecoder();
145 		d.readHeadersAndContentsFromInputStreamAndDecode(byteArrayInputStream);
146 
147 		assertEquals(0, byteArrayInputStream.available());
148 		assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty());
149 		assertEquals(Charset.forName("ISO-8859-2"), d.getCharset());
150 		assertTrue(d.isCharsetExplicitlySet());
151 		assertEquals("application/hl7-v2", d.getContentType());
152 		assertEquals(ourSampleMessage, d.getMessage());
153 		assertEquals("hello", d.getUsername());
154 		assertEquals("world", d.getPassword());
155 		assertEquals("/AppName", d.getPath());
156 
157 	}
158 
159 	@Test
160 	public void testDecodeFromStreamWithMultibyteSequences() throws Exception {
161 		ByteArrayOutputStream bos = new ByteArrayOutputStream();
162 		String msg = "POST /AppName HTTP/1.1\r\n" + "Content-Type: application/hl7-v2; charset=UTF-8\r\n" + "Content-Length: " + ourSampleMessageWithMultibyte.getBytes("UTF-8").length + "\r\n" + "Authorization: Basic aGVsbG86d29ybGQ=\r\n" + "\r\n";
163 		bos.write(msg.getBytes("ISO-8859-1"));
164 		bos.write(ourSampleMessageWithMultibyte.getBytes("UTF-8"));
165 		AbstractHl7OverHttpDecoder d = new Hl7OverHttpRequestDecoder();
166 		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bos.toByteArray());
167 		d.readHeadersAndContentsFromInputStreamAndDecode(byteArrayInputStream);
168 
169 		assertEquals(0, byteArrayInputStream.available());
170 		assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty());
171 		assertEquals(Charset.forName("UTF-8"), d.getCharset());
172 		assertTrue(d.isCharsetExplicitlySet());
173 		assertEquals("application/hl7-v2", d.getContentType());
174 		assertEquals(ourSampleMessageWithMultibyte, d.getMessage());
175 		assertEquals("hello", d.getUsername());
176 		assertEquals("world", d.getPassword());
177 		assertEquals("/AppName", d.getPath());
178 
179 	}
180 
181 	@Test
182 	public void testDecodeFromStreamWithCompression() throws Exception {
183 		byte[] sampleMessage = GZipUtils.compress(ourSampleMessageWithMultibyte.getBytes("UTF-8"));
184 
185 		ByteArrayOutputStream bos = new ByteArrayOutputStream();
186 		String msg = "POST /AppName HTTP/1.1\r\n" + 
187 				"Content-Type: application/hl7-v2; charset=UTF-8\r\n" + 
188 				"Content-Length: " + sampleMessage.length + "\r\n" + 
189 				"Content-Encoding: gzip\r\n" + 
190 				"Authorization: Basic aGVsbG86d29ybGQ=\r\n" + "\r\n";
191 		
192 		bos.write(msg.getBytes("ISO-8859-1"));
193 		bos.write(sampleMessage);
194 		AbstractHl7OverHttpDecoder d = new Hl7OverHttpRequestDecoder();
195 		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bos.toByteArray());
196 		d.readHeadersAndContentsFromInputStreamAndDecode(byteArrayInputStream);
197 
198 		assertEquals(0, byteArrayInputStream.available());
199 		assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty());
200 		assertEquals(Charset.forName("UTF-8"), d.getCharset());
201 		assertTrue(d.isCharsetExplicitlySet());
202 		assertEquals("application/hl7-v2", d.getContentType());
203 		assertEquals(ourSampleMessageWithMultibyte, d.getMessage());
204 		assertEquals("hello", d.getUsername());
205 		assertEquals("world", d.getPassword());
206 		assertEquals("/AppName", d.getPath());
207 
208 	}
209 
210 	@Test
211 	public void testDecodeFromStreamWithMultipleMessages() throws Exception {
212 
213 		ByteArrayOutputStream bos = new ByteArrayOutputStream();
214 		String msg = "POST /AppName HTTP/1.1\r\n" + "Content-Type: application/hl7-v2; charset=ISO-8859-2\r\n" + "Content-Length: " + ourSampleMessage.getBytes("ISO-8859-1").length + "\r\n" + "Authorization: Basic aGVsbG86d29ybGQ=\r\n" + "\r\n";
215 
216 		bos.write(msg.getBytes("ISO-8859-1"));
217 		bos.write(ourSampleMessage.getBytes("ISO-8859-2"));
218 		bos.write(msg.getBytes("ISO-8859-1"));
219 		bos.write(ourSampleMessage.getBytes("ISO-8859-2"));
220 
221 		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bos.toByteArray());
222 
223 		AbstractHl7OverHttpDecoder d = new Hl7OverHttpRequestDecoder();
224 		d.readHeadersAndContentsFromInputStreamAndDecode(byteArrayInputStream);
225 
226 		assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty());
227 		assertEquals(Charset.forName("ISO-8859-2"), d.getCharset());
228 		assertTrue(d.isCharsetExplicitlySet());
229 		assertEquals("application/hl7-v2", d.getContentType());
230 		assertEquals(ourSampleMessage, d.getMessage());
231 		assertEquals("hello", d.getUsername());
232 		assertEquals("world", d.getPassword());
233 		assertEquals("/AppName", d.getPath());
234 
235 		d = new Hl7OverHttpRequestDecoder();
236 		d.readHeadersAndContentsFromInputStreamAndDecode(byteArrayInputStream);
237 
238 		assertEquals(0, byteArrayInputStream.available());
239 		assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty());
240 		assertEquals(Charset.forName("ISO-8859-2"), d.getCharset());
241 		assertTrue(d.isCharsetExplicitlySet());
242 		assertEquals("application/hl7-v2", d.getContentType());
243 		assertEquals(ourSampleMessage, d.getMessage());
244 		assertEquals("hello", d.getUsername());
245 		assertEquals("world", d.getPassword());
246 		assertEquals("/AppName", d.getPath());
247 
248 	}
249 
250 	/**
251 	 * Simulate a network blip causing a delay mid-message
252 	 */
253 	@Test
254 	public void testDecodeFromStreamWithPauseInTheMiddleOfMessage() throws Exception {
255 
256 		ByteArrayOutputStream bos = new ByteArrayOutputStream();
257 		String msg = "POST /AppName HTTP/1.1\r\n" + "Content-Type: application/hl7-v2; charset=ISO-8859-2\r\n" + "Content-Length: " + ourSampleMessage.getBytes("ISO-8859-1").length + "\r\n" + "Authorization: Basic aGVsbG86d29ybGQ=\r\n" + "\r\n";
258 		bos.write(msg.getBytes("ISO-8859-1"));
259 		bos.write(ourSampleMessage.getBytes("ISO-8859-2"));
260 		AbstractHl7OverHttpDecoder d = new Hl7OverHttpRequestDecoder();
261 
262 		ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray());
263 		SplitInputStream is = new SplitInputStream(bais, msg.length() + 10);
264 
265 		d.readHeadersAndContentsFromInputStreamAndDecode(is);
266 
267 		assertEquals(0, bais.available());
268 		assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty());
269 		assertEquals(Charset.forName("ISO-8859-2"), d.getCharset());
270 		assertTrue(d.isCharsetExplicitlySet());
271 		assertEquals("application/hl7-v2", d.getContentType());
272 		assertEquals(ourSampleMessage, d.getMessage());
273 		assertEquals("hello", d.getUsername());
274 		assertEquals("world", d.getPassword());
275 		assertEquals("/AppName", d.getPath());
276 
277 	}
278 
279 	/**
280 	 * Simulate a network blip causing a delay mid-message
281 	 */
282 	@Test
283 	public void testDecodeFromStreamWithPauseInStatusLine() throws Exception {
284 
285 		ByteArrayOutputStream bos = new ByteArrayOutputStream();
286 		String msg = "POST /AppName HTTP/1.1\r\n" + "Content-Type: application/hl7-v2; charset=ISO-8859-2\r\n" + "Content-Length: " + ourSampleMessage.getBytes("ISO-8859-1").length + "\r\n" + "Authorization: Basic aGVsbG86d29ybGQ=\r\n" + "\r\n";
287 		bos.write(msg.getBytes("ISO-8859-1"));
288 		bos.write(ourSampleMessage.getBytes("ISO-8859-2"));
289 		AbstractHl7OverHttpDecoder d = new Hl7OverHttpRequestDecoder();
290 
291 		ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray());
292 		SplitInputStream is = new SplitInputStream(bais, 5);
293 
294 		d.readHeadersAndContentsFromInputStreamAndDecode(is);
295 
296 		assertEquals(0, bais.available());
297 		assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty());
298 		assertEquals(Charset.forName("ISO-8859-2"), d.getCharset());
299 		assertTrue(d.isCharsetExplicitlySet());
300 		assertEquals("application/hl7-v2", d.getContentType());
301 		assertEquals(ourSampleMessage, d.getMessage());
302 		assertEquals("hello", d.getUsername());
303 		assertEquals("world", d.getPassword());
304 		assertEquals("/AppName", d.getPath());
305 
306 	}
307 
308 	/**
309 	 * Simulate a network blip causing a delay mid-message
310 	 */
311 	@Test
312 	public void testDecodeFromStreamWithPauseInMiddleOfHeaders() throws Exception {
313 
314 		ByteArrayOutputStream bos = new ByteArrayOutputStream();
315 		String msg = "POST /AppName HTTP/1.1\r\n" + "Content-Type: application/hl7-v2; charset=ISO-8859-2\r\n" + "Content-Length: " + ourSampleMessage.getBytes("ISO-8859-1").length + "\r\n" + "Authorization: Basic aGVsbG86d29ybGQ=\r\n" + "\r\n";
316 		bos.write(msg.getBytes("ISO-8859-1"));
317 		bos.write(ourSampleMessage.getBytes("ISO-8859-2"));
318 		AbstractHl7OverHttpDecoder d = new Hl7OverHttpRequestDecoder();
319 
320 		ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray());
321 		SplitInputStream is = new SplitInputStream(bais, 30);
322 
323 		d.readHeadersAndContentsFromInputStreamAndDecode(is);
324 
325 		assertEquals(0, bais.available());
326 		assertTrue(d.getConformanceProblems().toString(), d.getConformanceProblems().isEmpty());
327 		assertEquals(Charset.forName("ISO-8859-2"), d.getCharset());
328 		assertTrue(d.isCharsetExplicitlySet());
329 		assertEquals("application/hl7-v2", d.getContentType());
330 		assertEquals(ourSampleMessage, d.getMessage());
331 		assertEquals("hello", d.getUsername());
332 		assertEquals("world", d.getPassword());
333 		assertEquals("/AppName", d.getPath());
334 
335 	}
336 }