001package ca.uhn.hl7v2.hoh.raw.server;
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.Entry;
014
015import org.junit.After;
016import org.junit.AfterClass;
017import org.junit.Before;
018import org.junit.BeforeClass;
019import org.junit.Test;
020import org.mortbay.jetty.Server;
021import org.mortbay.jetty.servlet.Context;
022import org.mortbay.jetty.servlet.ServletHolder;
023
024import ca.uhn.hl7v2.AcknowledgmentCode;
025import ca.uhn.hl7v2.DefaultHapiContext;
026import ca.uhn.hl7v2.HL7Exception;
027import ca.uhn.hl7v2.hoh.api.IAuthorizationServerCallback;
028import ca.uhn.hl7v2.hoh.api.IMessageHandler;
029import ca.uhn.hl7v2.hoh.api.IReceivable;
030import ca.uhn.hl7v2.hoh.api.IResponseSendable;
031import ca.uhn.hl7v2.hoh.api.MessageProcessingException;
032import ca.uhn.hl7v2.hoh.encoder.EncodingStyle;
033import ca.uhn.hl7v2.hoh.encoder.Hl7OverHttpRequestEncoder;
034import ca.uhn.hl7v2.hoh.llp.Hl7OverHttpLowerLayerProtocol;
035import ca.uhn.hl7v2.hoh.raw.api.RawSendable;
036import ca.uhn.hl7v2.hoh.util.RandomServerPortProvider;
037import ca.uhn.hl7v2.hoh.util.ServerRoleEnum;
038import ca.uhn.hl7v2.hoh.util.StringUtils;
039import ca.uhn.hl7v2.model.v25.message.ADT_A05;
040import ca.uhn.hl7v2.parser.DefaultXMLParser;
041import ca.uhn.hl7v2.parser.EncodingNotSupportedException;
042import ca.uhn.hl7v2.parser.GenericParser;
043
044public class HohRawServletTest implements IAuthorizationServerCallback, IMessageHandler<String> {
045
046        private static DefaultHapiContext ourHapiContext;
047        private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(HohRawServletTest.class);
048        private String myExpectedPassword;
049        private String myExpectedUri;
050        private String myExpectedUsername;
051        private String myMessage;
052        private String myResponse;
053        private int myPort;
054        private Server myServer;
055
056        @After
057        public void after() throws Exception {
058                myServer.stop();
059        }
060
061        public boolean authorize(String theUri, String theUsername, String thePassword) {
062                if (myExpectedUsername == null) {
063                        return true;
064                } else {
065                        if (!StringUtils.equals(myExpectedUri, theUri)) {
066                                return false;
067                        }
068                        if (!StringUtils.equals(myExpectedUsername, theUsername)) {
069                                return false;
070                        }
071                        if (!StringUtils.equals(myExpectedPassword, thePassword)) {
072                                return false;
073                        }
074                        return true;
075                }
076
077        }
078
079        @Before
080        public void before() throws Exception {
081                myPort = RandomServerPortProvider.findFreePort();
082                myServer = new Server(myPort);
083                Context context = new Context(myServer, "/", Context.SESSIONS);
084                HohRawServlet servlet = new HohRawServlet();
085                servlet.setAuthorizationCallback(this);
086                servlet.setMessageHandler(this);
087                context.addServlet(new ServletHolder(servlet), "/*");
088
089                myServer.start();
090
091                while (myServer.isStarting()) {
092                        ourLog.info("Waiting for server to start...");
093                        Thread.sleep(100);
094                }
095
096                myResponse = null;
097        }
098
099        public IResponseSendable<String> messageReceived(IReceivable<String> theMessage) throws MessageProcessingException {
100
101                myMessage = theMessage.getMessage();
102                try {
103                        if (myResponse == null) {
104                                myResponse = GenericParser.getInstanceWithNoValidation().parse(myMessage).generateACK().encode();
105                        }
106                        return new RawSendable(myResponse);
107                } catch (EncodingNotSupportedException e) {
108                        throw new MessageProcessingException(e);
109                } catch (HL7Exception e) {
110                        throw new MessageProcessingException(e);
111                } catch (IOException e) {
112                        throw new MessageProcessingException(e);
113                }
114
115        }
116
117        @Test
118        public void testSuccessWhenRequestHasNoCharsetSpecified() throws Exception {
119
120                String message = // -
121                "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + // -
122                                "EVN||200803051509\r" + // -
123                                "PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r"; // -
124                ADT_A05 msg = new ADT_A05();
125                msg.parse(message);
126
127                Hl7OverHttpLowerLayerProtocol llp = new Hl7OverHttpLowerLayerProtocol(ServerRoleEnum.CLIENT);
128                String charsetName = "ISO-8859-1";
129                llp.setPreferredCharset(Charset.forName(charsetName));
130
131                Hl7OverHttpRequestEncoder enc = new Hl7OverHttpRequestEncoder();
132                enc.setCharset(Charset.forName(charsetName));
133                enc.setUsername("hello");
134                enc.setPassword("world");
135                enc.setMessage(message);
136                enc.encode();
137
138                String urlString = "http://localhost:" + myPort + "/";
139                ourLog.info("URL: {}", urlString);
140                URL url = new URL(urlString);
141                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
142                conn.setRequestMethod("POST");
143
144                conn.setUseCaches(false);
145                conn.setDoInput(true);
146                conn.setDoOutput(true);
147
148                for (Entry<String, String> next : enc.getHeaders().entrySet()) {
149                        if (next.getKey().toLowerCase().equals("content-type")) {
150                                conn.setRequestProperty(next.getKey(), "application/hl7-v2");
151                        } else {
152                                conn.setRequestProperty(next.getKey(), next.getValue());
153                        }
154                }
155
156                DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
157                wr.write(enc.getData());
158                wr.flush();
159
160                // Get Response
161                InputStream is;
162                try {
163                        is = conn.getInputStream();
164                } catch (IOException e) {
165                        if (conn.getResponseCode() == 400 || conn.getResponseCode() == 500) {
166                                is = conn.getErrorStream();
167                        } else {
168                                throw e;
169                        }
170                }
171                BufferedReader rd = new BufferedReader(new InputStreamReader(is));
172                String line;
173                StringBuffer response = new StringBuffer();
174                while ((line = rd.readLine()) != null) {
175                        response.append(line);
176                        response.append('\r');
177                }
178                String responseString = response.toString();
179                ourLog.info("Response:\n{}", responseString);
180
181                assertEquals(EncodingStyle.ER7.getContentType(), conn.getHeaderField("Content-Type").replaceAll(";.*", ""));
182                assertEquals("UTF-8", conn.getHeaderField("Content-Type").replaceAll(".*;.*charset=", ""));
183                assertEquals(200, conn.getResponseCode());
184                assertEquals(message, myMessage);
185                assertEquals(myResponse, responseString);
186        }
187
188        @Test
189        public void testServlet() throws Exception {
190
191                String message = // -
192                "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + // -
193                                "EVN||200803051509\r" + // -
194                                "PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r"; // -
195                ADT_A05 msg = new ADT_A05();
196                msg.parse(message);
197
198                Hl7OverHttpLowerLayerProtocol llp = new Hl7OverHttpLowerLayerProtocol(ServerRoleEnum.CLIENT);
199                String charsetName = "ISO-8859-2";
200                llp.setPreferredCharset(Charset.forName(charsetName));
201
202                Hl7OverHttpRequestEncoder enc = new Hl7OverHttpRequestEncoder();
203                enc.setCharset(Charset.forName(charsetName));
204                enc.setUsername("hello");
205                enc.setPassword("world");
206                enc.setMessage(message);
207                enc.encode();
208
209                String urlString = "http://localhost:" + myPort + "/";
210                ourLog.info("URL: {}", urlString);
211                URL url = new URL(urlString);
212                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
213                conn.setRequestMethod("POST");
214
215                conn.setUseCaches(false);
216                conn.setDoInput(true);
217                conn.setDoOutput(true);
218
219                for (Entry<String, String> next : enc.getHeaders().entrySet()) {
220                        conn.setRequestProperty(next.getKey(), next.getValue());
221                }
222
223                DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
224                wr.write(enc.getData());
225                wr.flush();
226
227                // Get Response
228                InputStream is;
229                try {
230                        is = conn.getInputStream();
231                } catch (IOException e) {
232                        if (conn.getResponseCode() == 400 || conn.getResponseCode() == 500) {
233                                is = conn.getErrorStream();
234                        } else {
235                                throw e;
236                        }
237                }
238                BufferedReader rd = new BufferedReader(new InputStreamReader(is));
239                String line;
240                StringBuffer response = new StringBuffer();
241                while ((line = rd.readLine()) != null) {
242                        response.append(line);
243                        response.append('\r');
244                }
245                String responseString = response.toString();
246                ourLog.info("Response:\n{}", responseString);
247
248                assertEquals(EncodingStyle.ER7.getContentType(), conn.getHeaderField("Content-Type").replaceAll(";.*", ""));
249                assertEquals(charsetName, conn.getHeaderField("Content-Type").replaceAll(".*;.*charset=", ""));
250                assertEquals(200, conn.getResponseCode());
251                assertEquals(message, myMessage);
252                assertEquals(myResponse, responseString);
253
254        }
255
256        @Test
257        public void testLargeMessage() throws Exception {
258
259                StringBuilder b= new StringBuilder();
260                for (int a = 0; a < 100000; a++) {
261                        b.append('a');
262                }
263                
264                String message = // -
265                "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + // -
266                                "EVN||200803051509\r" + // -
267                                "PID|||" + b + "^^^SSN^SSN^^20070103\r"; // -
268                ADT_A05 msg = new ADT_A05();
269                msg.parse(message);
270
271                Hl7OverHttpLowerLayerProtocol llp = new Hl7OverHttpLowerLayerProtocol(ServerRoleEnum.CLIENT);
272                String charsetName = "ISO-8859-2";
273                llp.setPreferredCharset(Charset.forName(charsetName));
274
275                Hl7OverHttpRequestEncoder enc = new Hl7OverHttpRequestEncoder();
276                enc.setCharset(Charset.forName(charsetName));
277                enc.setUsername("hello");
278                enc.setPassword("world");
279                enc.setMessage(message);
280                enc.encode();
281
282                String urlString = "http://localhost:" + myPort + "/";
283                ourLog.info("URL: {}", urlString);
284                URL url = new URL(urlString);
285                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
286                conn.setRequestMethod("POST");
287
288                conn.setUseCaches(false);
289                conn.setDoInput(true);
290                conn.setDoOutput(true);
291
292                for (Entry<String, String> next : enc.getHeaders().entrySet()) {
293                        conn.setRequestProperty(next.getKey(), next.getValue());
294                }
295
296                DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
297                wr.write(enc.getData());
298                wr.flush();
299
300                // Get Response
301                InputStream is;
302                try {
303                        is = conn.getInputStream();
304                } catch (IOException e) {
305                        if (conn.getResponseCode() == 400 || conn.getResponseCode() == 500) {
306                                is = conn.getErrorStream();
307                        } else {
308                                throw e;
309                        }
310                }
311                BufferedReader rd = new BufferedReader(new InputStreamReader(is));
312                String line;
313                StringBuffer response = new StringBuffer();
314                while ((line = rd.readLine()) != null) {
315                        response.append(line);
316                        response.append('\r');
317                }
318                String responseString = response.toString();
319                ourLog.info("Response:\n{}", responseString);
320
321                assertEquals(EncodingStyle.ER7.getContentType(), conn.getHeaderField("Content-Type").replaceAll(";.*", ""));
322                assertEquals(charsetName, conn.getHeaderField("Content-Type").replaceAll(".*;.*charset=", ""));
323                assertEquals(200, conn.getResponseCode());
324                assertEquals(message, myMessage);
325                assertEquals(myResponse, responseString);
326
327        }
328
329        @Test
330        public void testServletAR() throws Exception {
331
332                String message = // -
333                "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + // -
334                                "EVN||200803051509\r" + // -
335                                "PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r"; // -
336                ADT_A05 msg = new ADT_A05();
337                msg.parse(message);
338
339                myResponse = msg.generateACK(AcknowledgmentCode.AR, new HL7Exception("ewrerwe")).encode();
340
341                Hl7OverHttpLowerLayerProtocol llp = new Hl7OverHttpLowerLayerProtocol(ServerRoleEnum.CLIENT);
342                String charsetName = "ISO-8859-2";
343                llp.setPreferredCharset(Charset.forName(charsetName));
344
345                Hl7OverHttpRequestEncoder enc = new Hl7OverHttpRequestEncoder();
346                enc.setCharset(Charset.forName(charsetName));
347                enc.setUsername("hello");
348                enc.setPassword("world");
349                enc.setMessage(message);
350                enc.encode();
351
352                String urlString = "http://localhost:" + myPort + "/";
353                ourLog.info("URL: {}", urlString);
354                URL url = new URL(urlString);
355                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
356                conn.setRequestMethod("POST");
357
358                conn.setUseCaches(false);
359                conn.setDoInput(true);
360                conn.setDoOutput(true);
361                for (Entry<String, String> next : enc.getHeaders().entrySet()) {
362                        conn.setRequestProperty(next.getKey(), next.getValue());
363                }
364
365                DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
366                wr.write(enc.getData());
367                wr.flush();
368
369                // Get Response
370                InputStream is;
371                try {
372                        is = conn.getInputStream();
373                } catch (IOException e) {
374                        if (conn.getResponseCode() == 400 || conn.getResponseCode() == 500) {
375                                is = conn.getErrorStream();
376                        } else {
377                                throw e;
378                        }
379                }
380                BufferedReader rd = new BufferedReader(new InputStreamReader(is));
381                String line;
382                StringBuffer response = new StringBuffer();
383                while ((line = rd.readLine()) != null) {
384                        response.append(line);
385                        response.append('\r');
386                }
387                String responseString = response.toString();
388                ourLog.info("Response:\n{}", responseString);
389
390                assertEquals(EncodingStyle.ER7.getContentType(), conn.getHeaderField("Content-Type").replaceAll(";.*", ""));
391                assertEquals(charsetName, conn.getHeaderField("Content-Type").replaceAll(".*;.*charset=", ""));
392                assertEquals(200, conn.getResponseCode());
393                assertEquals(message, myMessage);
394                assertEquals(myResponse, responseString);
395
396        }
397
398        @Test
399        public void testServletAE() throws Exception {
400
401                String message = // -
402                "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + // -
403                                "EVN||200803051509\r" + // -
404                                "PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r"; // -
405                ADT_A05 msg = new ADT_A05();
406                msg.parse(message);
407
408                myResponse = msg.generateACK(AcknowledgmentCode.AE, new HL7Exception("ewrerwe")).encode();
409
410                Hl7OverHttpLowerLayerProtocol llp = new Hl7OverHttpLowerLayerProtocol(ServerRoleEnum.CLIENT);
411                String charsetName = "ISO-8859-2";
412                llp.setPreferredCharset(Charset.forName(charsetName));
413
414                Hl7OverHttpRequestEncoder enc = new Hl7OverHttpRequestEncoder();
415                enc.setCharset(Charset.forName(charsetName));
416                enc.setUsername("hello");
417                enc.setPassword("world");
418                enc.setMessage(message);
419                enc.encode();
420
421                String urlString = "http://localhost:" + myPort + "/";
422                ourLog.info("URL: {}", urlString);
423                URL url = new URL(urlString);
424                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
425                conn.setRequestMethod("POST");
426
427                conn.setUseCaches(false);
428                conn.setDoInput(true);
429                conn.setDoOutput(true);
430                for (Entry<String, String> next : enc.getHeaders().entrySet()) {
431                        conn.setRequestProperty(next.getKey(), next.getValue());
432                }
433
434                DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
435                wr.write(enc.getData());
436                wr.flush();
437
438                // Get Response
439                InputStream is;
440                try {
441                        is = conn.getInputStream();
442                } catch (IOException e) {
443                        if (conn.getResponseCode() == 400 || conn.getResponseCode() == 500) {
444                                is = conn.getErrorStream();
445                        } else {
446                                throw e;
447                        }
448                }
449                BufferedReader rd = new BufferedReader(new InputStreamReader(is));
450                String line;
451                StringBuffer response = new StringBuffer();
452                while ((line = rd.readLine()) != null) {
453                        response.append(line);
454                        response.append('\r');
455                }
456                String responseString = response.toString();
457                ourLog.info("Response:\n{}", responseString);
458
459                assertEquals(EncodingStyle.ER7.getContentType(), conn.getHeaderField("Content-Type").replaceAll(";.*", ""));
460                assertEquals(charsetName, conn.getHeaderField("Content-Type").replaceAll(".*;.*charset=", ""));
461                assertEquals(200, conn.getResponseCode());
462                assertEquals(message, myMessage);
463                assertEquals(myResponse, responseString);
464
465        }
466
467        @Test
468        public void testServletSimpleXml() throws Exception {
469
470                String message = // -
471                "MSH|^~\\&|||||200803051508||ADT^A31|2|P|2.5\r" + // -
472                                "EVN||200803051509\r" + // -
473                                "PID|||ZZZZZZ83M64Z148R^^^SSN^SSN^^20070103\r"; // -
474                ADT_A05 msg = new ADT_A05();
475                msg.parse(message);
476
477                message = DefaultXMLParser.getInstanceWithNoValidation().encode(msg);
478
479                Hl7OverHttpLowerLayerProtocol llp = new Hl7OverHttpLowerLayerProtocol(ServerRoleEnum.CLIENT);
480                String charsetName = "ISO-8859-2";
481                llp.setPreferredCharset(Charset.forName(charsetName));
482
483                Hl7OverHttpRequestEncoder enc = new Hl7OverHttpRequestEncoder();
484                enc.setCharset(Charset.forName(charsetName));
485                enc.setUsername("hello");
486                enc.setPassword("world");
487                enc.setMessage(message);
488                enc.encode();
489
490                String urlString = "http://localhost:" + myPort + "/";
491                ourLog.info("URL: {}", urlString);
492                URL url = new URL(urlString);
493                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
494                conn.setRequestMethod("POST");
495
496                conn.setUseCaches(false);
497                conn.setDoInput(true);
498                conn.setDoOutput(true);
499                for (Entry<String, String> next : enc.getHeaders().entrySet()) {
500                        conn.setRequestProperty(next.getKey(), next.getValue());
501                }
502
503                DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
504                wr.write(enc.getData());
505                wr.flush();
506
507                // Get Response
508                InputStream is;
509                try {
510                        is = conn.getInputStream();
511                } catch (IOException e) {
512                        if (conn.getResponseCode() == 400 || conn.getResponseCode() == 500) {
513                                is = conn.getErrorStream();
514                        } else {
515                                throw e;
516                        }
517                }
518                BufferedReader rd = new BufferedReader(new InputStreamReader(is));
519                String line;
520                StringBuffer response = new StringBuffer();
521                while ((line = rd.readLine()) != null) {
522                        response.append(line);
523                        response.append('\r');
524                }
525                String responseString = response.toString();
526                ourLog.info("Response:\n{}", responseString);
527
528                assertEquals(EncodingStyle.XML.getContentType(), conn.getHeaderField("Content-Type").replaceAll(";.*", ""));
529                assertEquals(charsetName, conn.getHeaderField("Content-Type").replaceAll(".*;.*charset=", ""));
530                assertEquals(200, conn.getResponseCode());
531                assertEquals(message, myMessage);
532                assertEquals(myResponse.replaceAll("(\\r|\\n)+", " "), responseString.replaceAll("(\\r|\\n)+", " "));
533
534        }
535
536        @AfterClass
537        public static void afterClass() throws InterruptedException {
538                // Thread.sleep(1000000);
539                ourHapiContext.getExecutorService().shutdown();
540        }
541
542        @BeforeClass
543        public static void beforeClass() {
544                System.setProperty("DEBUG", "true");
545
546                ourHapiContext = new DefaultHapiContext();
547        }
548
549}