001package ca.uhn.hl7v2.hoh.llp;
002
003import static org.junit.Assert.*;
004
005import java.io.BufferedReader;
006import java.io.DataOutputStream;
007import java.io.IOException;
008import java.io.InputStream;
009import java.io.InputStreamReader;
010import java.net.HttpURLConnection;
011import java.net.URL;
012import java.nio.charset.Charset;
013import java.util.Map;
014import java.util.Map.Entry;
015
016import ca.uhn.hl7v2.protocol.ReceivingApplication;
017import ca.uhn.hl7v2.protocol.ReceivingApplicationException;
018import org.junit.After;
019import org.junit.Before;
020import org.junit.Test;
021
022import ca.uhn.hl7v2.AcknowledgmentCode;
023import ca.uhn.hl7v2.HL7Exception;
024import ca.uhn.hl7v2.app.Application;
025import ca.uhn.hl7v2.app.ApplicationException;
026import ca.uhn.hl7v2.app.Connection;
027import ca.uhn.hl7v2.app.ConnectionListener;
028import ca.uhn.hl7v2.app.SimpleServer;
029import ca.uhn.hl7v2.hoh.encoder.EncodingStyle;
030import ca.uhn.hl7v2.hoh.encoder.Hl7OverHttpRequestEncoder;
031import ca.uhn.hl7v2.hoh.sign.BouncyCastleCmsMessageSignerTest;
032import ca.uhn.hl7v2.hoh.util.RandomServerPortProvider;
033import ca.uhn.hl7v2.hoh.util.ServerRoleEnum;
034import ca.uhn.hl7v2.model.Message;
035import ca.uhn.hl7v2.parser.DefaultXMLParser;
036import ca.uhn.hl7v2.parser.GenericParser;
037import ca.uhn.hl7v2.parser.PipeParser;
038
039public class LlpServerTest implements ReceivingApplication<Message>, ConnectionListener {
040
041        private int myPort;
042        private Hl7OverHttpLowerLayerProtocol myLlp;
043        private SimpleServer myServer;
044        private Message myMessage;
045        private int myConnections;
046        private Message myResponse;
047
048        @Before
049        public void before() throws InterruptedException {
050                myPort = RandomServerPortProvider.findFreePort();
051
052                myLlp = new Hl7OverHttpLowerLayerProtocol(ServerRoleEnum.SERVER);
053                myServer = new SimpleServer(myPort, myLlp, GenericParser.getInstanceWithNoValidation());
054                myServer.registerApplication("*", "*", this);
055                myServer.registerConnectionListener(this);
056                myMessage = (Message) null;
057                myResponse = (Message) null;
058                myConnections = 0;
059        }
060
061        @Test
062        public void testSendSimple() throws Exception {
063                myServer.startAndWait();
064
065                String message = // -
066                "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + // -
067                                "EVN||200803051509\r" + // -
068                                "PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r"; // -
069
070                Hl7OverHttpRequestEncoder enc = new Hl7OverHttpRequestEncoder();
071                String charsetName = "ISO-8859-2";
072                enc.setCharset(Charset.forName(charsetName));
073                enc.setUsername("hello");
074                enc.setPassword("world");
075                enc.setMessage(message);
076                enc.encode();
077
078                String urlString = "http://localhost:" + myPort + "/";
079                ourLog.info("URL: {}", urlString);
080                URL url = new URL(urlString);
081                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
082                conn.setRequestMethod("POST");
083
084                conn.setUseCaches(false);
085                conn.setDoInput(true);
086                conn.setDoOutput(true);
087                for (Entry<String, String> next : enc.getHeaders().entrySet()) {
088                        conn.setRequestProperty(next.getKey(), next.getValue());
089                }
090
091                DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
092                wr.write(enc.getData());
093                wr.flush();
094
095                // Get Response
096                InputStream is = conn.getInputStream();
097                BufferedReader rd = new BufferedReader(new InputStreamReader(is));
098                String line;
099                StringBuffer response = new StringBuffer();
100                while ((line = rd.readLine()) != null) {
101                        response.append(line);
102                        response.append('\r');
103                }
104                String responseString = response.toString();
105                ourLog.info("Response:\n{}", responseString);
106
107                assertEquals(EncodingStyle.ER7.getContentType(), conn.getHeaderField("Content-Type").replaceAll(";.*", ""));
108                assertEquals(charsetName, conn.getHeaderField("Content-Type").replaceAll(".*;.*charset=", ""));
109                assertEquals(200, conn.getResponseCode());
110                assertEquals(message, myMessage.encode());
111                assertEquals(myResponse.encode(), responseString);
112
113        }
114
115        @Test
116        public void testSendSimpleXml() throws Exception {
117                myServer.startAndWait();
118
119                String message = // -
120                "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + // -
121                                "EVN||200803051509\r" + // -
122                                "PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r"; // -
123                message = DefaultXMLParser.getInstanceWithNoValidation().encode(PipeParser.getInstanceWithNoValidation().parse(message));
124                
125                Hl7OverHttpRequestEncoder enc = new Hl7OverHttpRequestEncoder();
126                String charsetName = "ISO-8859-2";
127                enc.setCharset(Charset.forName(charsetName));
128                enc.setUsername("hello");
129                enc.setPassword("world");
130                enc.setMessage(message);
131                enc.encode();
132
133                String urlString = "http://localhost:" + myPort + "/";
134                ourLog.info("URL: {}", urlString);
135                URL url = new URL(urlString);
136                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
137                conn.setRequestMethod("POST");
138
139                conn.setUseCaches(false);
140                conn.setDoInput(true);
141                conn.setDoOutput(true);
142                for (Entry<String, String> next : enc.getHeaders().entrySet()) {
143                        conn.setRequestProperty(next.getKey(), next.getValue());
144                }
145
146                DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
147                wr.write(enc.getData());
148                wr.flush();
149
150                // Get Response
151                InputStream is = conn.getInputStream();
152                BufferedReader rd = new BufferedReader(new InputStreamReader(is));
153                String line;
154                StringBuffer response = new StringBuffer();
155                while ((line = rd.readLine()) != null) {
156                        response.append(line);
157                        response.append('\r');
158                }
159                String responseString = response.toString();
160                ourLog.info("Response:\n{}", responseString);
161
162                assertEquals(EncodingStyle.XML.getContentType(), conn.getHeaderField("Content-Type").replaceAll(";.*", ""));
163                assertEquals(charsetName, conn.getHeaderField("Content-Type").replaceAll(".*;.*charset=", ""));
164                assertEquals(200, conn.getResponseCode());
165                assertEquals(message, myMessage.encode());
166                
167                String expected = myResponse.encode().replaceAll("<\\?.*\\?>", "").replaceAll("(\\r|\\n)+", "\n").trim();
168                String actual = responseString.replaceAll("<\\?.*\\?>", "").replaceAll("(\\r|\\n)+", "\n").trim();
169                assertEquals(expected, actual);
170
171        }
172
173        @Test
174        public void testReplyWithAE() throws Exception {
175                myServer.startAndWait();
176
177                String message = // -
178                "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + // -
179                                "EVN||200803051509\r" + // -
180                                "PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r"; // -
181
182                myResponse = PipeParser.getInstanceWithNoValidation().parse(message).generateACK(AcknowledgmentCode.AE, new HL7Exception("blah"));
183                
184                Hl7OverHttpRequestEncoder enc = new Hl7OverHttpRequestEncoder();
185                String charsetName = "ISO-8859-2";
186                enc.setCharset(Charset.forName(charsetName));
187                enc.setUsername("hello");
188                enc.setPassword("world");
189                enc.setMessage(message);
190                enc.encode();
191
192                String urlString = "http://localhost:" + myPort + "/";
193                ourLog.info("URL: {}", urlString);
194                URL url = new URL(urlString);
195                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
196                conn.setRequestMethod("POST");
197
198                conn.setUseCaches(false);
199                conn.setDoInput(true);
200                conn.setDoOutput(true);
201                for (Entry<String, String> next : enc.getHeaders().entrySet()) {
202                        conn.setRequestProperty(next.getKey(), next.getValue());
203                }
204
205                DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
206                wr.write(enc.getData());
207                wr.flush();
208
209                // Get Response
210                InputStream is;
211                try {
212                        is = conn.getInputStream();
213                } catch (IOException e) {
214                        if (conn.getResponseCode() == 400 || conn.getResponseCode() == 500) {
215                                is = conn.getErrorStream();
216                        } else {
217                                throw e;
218                        }
219                }
220                BufferedReader rd = new BufferedReader(new InputStreamReader(is));
221                String line;
222                StringBuffer response = new StringBuffer();
223                while ((line = rd.readLine()) != null) {
224                        response.append(line);
225                        response.append('\r');
226                }
227                String responseString = response.toString();
228                ourLog.info("Response:\n{}", responseString);
229
230                assertEquals(EncodingStyle.ER7.getContentType(), conn.getHeaderField("Content-Type").replaceAll(";.*", ""));
231                assertEquals(charsetName, conn.getHeaderField("Content-Type").replaceAll(".*;.*charset=", ""));
232                assertEquals(200, conn.getResponseCode());
233                assertEquals(message, myMessage.encode());
234                assertEquals(myResponse.encode(), responseString);
235
236        }
237
238        @Test
239        public void testReplyWithAR() throws Exception {
240                myServer.startAndWait();
241
242                String message = // -
243                "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + // -
244                                "EVN||200803051509\r" + // -
245                                "PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r"; // -
246
247                myResponse = PipeParser.getInstanceWithNoValidation().parse(message)
248                                .generateACK(AcknowledgmentCode.AR, new HL7Exception("blah"));
249                
250                Hl7OverHttpRequestEncoder enc = new Hl7OverHttpRequestEncoder();
251                String charsetName = "ISO-8859-2";
252                enc.setCharset(Charset.forName(charsetName));
253                enc.setUsername("hello");
254                enc.setPassword("world");
255                enc.setMessage(message);
256                enc.encode();
257
258                String urlString = "http://localhost:" + myPort + "/";
259                ourLog.info("URL: {}", urlString);
260                URL url = new URL(urlString);
261                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
262                conn.setRequestMethod("POST");
263
264                conn.setUseCaches(false);
265                conn.setDoInput(true);
266                conn.setDoOutput(true);
267                for (Entry<String, String> next : enc.getHeaders().entrySet()) {
268                        conn.setRequestProperty(next.getKey(), next.getValue());
269                }
270
271                DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
272                wr.write(enc.getData());
273                wr.flush();
274
275                // Get Response
276                InputStream is;
277                try {
278                        is = conn.getInputStream();
279                } catch (IOException e) {
280                        if (conn.getResponseCode() == 400 || conn.getResponseCode() == 500) {
281                                is = conn.getErrorStream();
282                        } else {
283                                throw e;
284                        }
285                }
286                BufferedReader rd = new BufferedReader(new InputStreamReader(is));
287                String line;
288                StringBuffer response = new StringBuffer();
289                while ((line = rd.readLine()) != null) {
290                        response.append(line);
291                        response.append('\r');
292                }
293                String responseString = response.toString();
294                ourLog.info("Response:\n{}", responseString);
295
296                assertEquals(EncodingStyle.ER7.getContentType(), conn.getHeaderField("Content-Type").replaceAll(";.*", ""));
297                assertEquals(charsetName, conn.getHeaderField("Content-Type").replaceAll(".*;.*charset=", ""));
298                assertEquals(200, conn.getResponseCode());
299                assertEquals(message, myMessage.encode());
300                assertEquals(myResponse.encode(), responseString);
301
302        }
303        
304        @Test
305        public void testSendPersistentConnection() throws Exception {
306                myServer.startAndWait();
307
308                String message = // -
309                "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + // -
310                                "EVN||200803051509\r" + // -
311                                "PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r"; // -
312
313                Hl7OverHttpRequestEncoder enc = new Hl7OverHttpRequestEncoder();
314                enc.setCharset(Charset.forName("ISO-8859-1"));
315                enc.setUsername("hello");
316                enc.setPassword("world");
317                enc.setMessage(message);
318                enc.encode();
319
320                String urlString = "http://localhost:" + myPort + "/";
321                ourLog.info("URL: {}", urlString);
322                URL url = new URL(urlString);
323                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
324                conn.setRequestMethod("POST");
325
326                conn.setUseCaches(false);
327                conn.setDoInput(true);
328                conn.setDoOutput(true);
329                for (Entry<String, String> next : enc.getHeaders().entrySet()) {
330                        conn.setRequestProperty(next.getKey(), next.getValue());
331                }
332
333                DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
334                wr.write(enc.getData());
335                wr.flush();
336                wr.close();
337
338                // Get Response
339                InputStream is = conn.getInputStream();
340                BufferedReader rd = new BufferedReader(new InputStreamReader(is));
341                String line;
342                StringBuffer response = new StringBuffer();
343                while ((line = rd.readLine()) != null) {
344                        response.append(line);
345                        response.append('\r');
346                }
347                is.close();
348                String responseString = response.toString();
349                ourLog.info("Response:\n{}", responseString);
350
351                assertEquals(200, conn.getResponseCode());
352                assertEquals(message, myMessage.encode());
353                assertEquals(myResponse.encode(), responseString);
354
355                // Send a second message
356                message = // -
357                "MSH|^~\\&|||||200803051508||ADT^A31|99999|P|2.5\r" + // -
358                                "EVN||200803051509\r" + // -
359                                "PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r"; // -
360
361                enc = new Hl7OverHttpRequestEncoder();
362                enc.setCharset(Charset.forName("ISO-8859-1"));
363                enc.setUsername("hello");
364                enc.setPassword("world");
365                enc.setMessage(message);
366                enc.encode();
367
368                conn = (HttpURLConnection) url.openConnection();
369                conn.setRequestMethod("POST");
370
371                conn.setUseCaches(false);
372                conn.setDoInput(true);
373                conn.setDoOutput(true);
374                for (Entry<String, String> next : enc.getHeaders().entrySet()) {
375                        conn.setRequestProperty(next.getKey(), next.getValue());
376                }
377
378                wr = new DataOutputStream(conn.getOutputStream());
379                wr.write(enc.getData());
380                wr.flush();
381
382                // Get Response
383                is = conn.getInputStream();
384                rd = new BufferedReader(new InputStreamReader(is));
385                response = new StringBuffer();
386                while ((line = rd.readLine()) != null) {
387                        response.append(line);
388                        response.append('\r');
389                }
390                responseString = response.toString();
391                ourLog.info("Response:\n{}", responseString);
392
393                assertEquals(200, conn.getResponseCode());
394                assertEquals(message, myMessage.encode());
395                assertEquals(myResponse.encode(), responseString);
396                assertEquals(1, myConnections);
397        }
398
399        private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(LlpServerTest.class);
400
401        @After
402        public void after() {
403                myServer.stopAndWait();
404        }
405
406        public boolean canProcess(Message theArg0) {
407                return true;
408        }
409
410        public Message processMessage(Message theArg0, Map<String, Object> metadata)
411            throws ReceivingApplicationException, HL7Exception {
412                myMessage = theArg0;
413                if (myResponse != null) {
414                        return myResponse;
415                }
416                try {
417                        myResponse = theArg0.generateACK();
418                        return myResponse;
419                } catch (IOException e) {
420                        fail(e.getMessage());
421                        throw new HL7Exception(e);
422                }
423        }
424
425        public void connectionDiscarded(Connection theArg0) {
426                // ignore
427        }
428
429        public void connectionReceived(Connection theArg0) {
430                myConnections++;
431        }
432
433        
434        @Test
435        public void testSendWithClientSigner() throws Exception {
436                myLlp.setSigner(BouncyCastleCmsMessageSignerTest.createVerifier());
437                myServer.startAndWait();
438
439                String message = // -
440                "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + // -
441                                "EVN||200803051509\r" + // -
442                                "PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r"; // -
443
444                Hl7OverHttpRequestEncoder enc = new Hl7OverHttpRequestEncoder();
445                enc.setCharset(Charset.forName("ISO-8859-1"));
446                enc.setUsername("hello");
447                enc.setPassword("world");
448                enc.setMessage(message);
449                enc.setSigner(BouncyCastleCmsMessageSignerTest.createSigner());
450                enc.encode();
451
452                String urlString = "http://localhost:" + myPort + "/";
453                ourLog.info("URL: {}", urlString);
454                URL url = new URL(urlString);
455                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
456                conn.setRequestMethod("POST");
457
458                conn.setUseCaches(false);
459                conn.setDoInput(true);
460                conn.setDoOutput(true);
461                for (Entry<String, String> next : enc.getHeaders().entrySet()) {
462                        conn.setRequestProperty(next.getKey(), next.getValue());
463                }
464
465                DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
466                wr.write(enc.getData());
467                wr.flush();
468
469                // Get Response
470                InputStream is = conn.getInputStream();
471                BufferedReader rd = new BufferedReader(new InputStreamReader(is));
472                String line;
473                StringBuffer response = new StringBuffer();
474                while ((line = rd.readLine()) != null) {
475                        response.append(line);
476                        response.append('\r');
477                }
478                String responseString = response.toString();
479                ourLog.info("Response:\n{}", responseString);
480
481                assertEquals(200, conn.getResponseCode());
482                assertEquals(message, myMessage.encode());
483                assertEquals(myResponse.encode(), responseString);
484
485        }
486
487}