Coverage Report - ca.uhn.hl7v2.app.HL7ServerTestHelper
 
Classes in this File Line Coverage Branch Coverage Complexity
HL7ServerTestHelper
0%
0/115
0%
0/26
4
HL7ServerTestHelper$CommentFilterReader
0%
0/37
0%
0/34
4
 
 1  
 /*
 2  
  * HL7ServerTest.java
 3  
  */
 4  
 
 5  
 package ca.uhn.hl7v2.app;
 6  
 
 7  
 import java.io.BufferedReader;
 8  
 import java.io.FileNotFoundException;
 9  
 import java.io.IOException;
 10  
 import java.io.InputStream;
 11  
 import java.io.InputStreamReader;
 12  
 import java.io.OutputStream;
 13  
 import java.io.PushbackReader;
 14  
 import java.io.Reader;
 15  
 import java.net.Socket;
 16  
 import java.util.ArrayList;
 17  
 import java.util.GregorianCalendar;
 18  
 import java.util.List;
 19  
 import java.util.regex.Matcher;
 20  
 import java.util.regex.Pattern;
 21  
 
 22  
 import org.apache.commons.cli.CommandLine;
 23  
 import org.apache.commons.cli.CommandLineParser;
 24  
 import org.apache.commons.cli.HelpFormatter;
 25  
 import org.apache.commons.cli.Options;
 26  
 import org.apache.commons.cli.ParseException;
 27  
 import org.apache.commons.cli.PosixParser;
 28  
 import org.slf4j.Logger;
 29  
 import org.slf4j.LoggerFactory;
 30  
 
 31  
 /**
 32  
  * Helper class used to send messages from a flat file to 
 33  
  * an ip and port. 
 34  
  * 
 35  
  * Messasges are sent using MLLP and ACK protocal
 36  
  * 
 37  
  * @author Laura Bright
 38  
  * @author Neal Acharya
 39  
  * 
 40  
  * @version $Revision: 1.2 $ updated on $Date: 2009-03-18 23:27:58 $ by $Author: jamesagnew $
 41  
  * @deprecated
 42  
  */
 43  
 public class HL7ServerTestHelper {
 44  
     
 45  0
     private static final Logger ourLog = LoggerFactory.getLogger(HL7ServerTestHelper.class);
 46  
     
 47  
     private static final String HL7_START_OF_MESSAGE = "\u000b";
 48  
     private static final String HL7_END_OF_MESSGAE = "\u001c";
 49  
 
 50  0
     private String host = null;
 51  
     
 52  0
     private int port = 0;
 53  
 
 54  0
     private Socket socket = null;
 55  
 
 56  0
     private OutputStream os = null;
 57  0
     private InputStream is = null;
 58  
     
 59  0
     public HL7ServerTestHelper(String host, int port) {
 60  0
         this.host = host;
 61  0
         this.port = port;
 62  0
     }
 63  
 
 64  
     /*
 65  
      * 
 66  
      */
 67  
     public void openSocket() throws IOException{
 68  0
         socket = new Socket(host, port);
 69  0
         socket.setSoLinger(true, 1000);
 70  
         
 71  0
         os = socket.getOutputStream();
 72  0
         is = socket.getInputStream();
 73  0
     }
 74  
     
 75  
     /**
 76  
      * 
 77  
      *
 78  
      */
 79  
     public void closeSocket() {
 80  
         try {
 81  0
             Socket sckt = socket;
 82  0
             socket = null;
 83  0
             if (sckt != null)
 84  0
                 sckt.close();
 85  
         }
 86  0
         catch (Exception e) {
 87  0
             ourLog.error(e.getMessage(), e);
 88  0
         }
 89  0
     }
 90  
  
 91  
     
 92  
     public int process( InputStream theMsgInputStream ) throws FileNotFoundException, IOException
 93  
     {
 94  
      
 95  0
             BufferedReader in = null;
 96  
             try {
 97  0
                 in = new BufferedReader( 
 98  
                         new CommentFilterReader( new InputStreamReader( theMsgInputStream ) )
 99  
                     );
 100  
                         
 101  0
                 StringBuffer rawMsgBuffer = new StringBuffer();
 102  
                 
 103  
                 //String line = in.readLine();
 104  0
                 int c = 0;
 105  0
                         while( (c = in.read()) >= 0) {
 106  0
                                 rawMsgBuffer.append( (char) c);
 107  
                         }
 108  
                         
 109  0
                         String[] messages = getHL7Messages(rawMsgBuffer.toString());
 110  0
                 int retVal = 0;
 111  
                 
 112  
                 //start time
 113  0
                 long startTime = new GregorianCalendar().getTimeInMillis(); 
 114  
                     
 115  
                     
 116  0
                         for (int i = 0; i < messages.length; i++) {
 117  0
                                 sendMessage(messages[i]);        
 118  0
                                 readAck();        
 119  0
                     retVal++;
 120  
                         }
 121  
                 
 122  
                 //end time
 123  0
                 long endTime =  new GregorianCalendar().getTimeInMillis();
 124  
                 
 125  
                 //elapsed time
 126  0
                 long elapsedTime = (endTime - startTime) / 1000;
 127  
                 
 128  0
                 ourLog.info("{} messages sent.", retVal);
 129  0
                 ourLog.info("Elapsed Time in seconds: {} ", elapsedTime);
 130  0
                 return retVal;
 131  
             } finally {
 132  0
                     if (in != null) {
 133  
                             try {
 134  0
                                         in.close();
 135  0
                                 } catch (IOException e) {
 136  0
                                 }
 137  
                     }
 138  
             }
 139  
                         
 140  
         
 141  
     }
 142  
     
 143  
         private String readAck() throws IOException
 144  
         {
 145  0
                 StringBuffer stringbuffer = new StringBuffer();
 146  0
                 int i = 0;
 147  
                 do {
 148  0
                         i = is.read();
 149  0
                         if (i == -1)
 150  0
                                 return null;
 151  
             
 152  0
                         stringbuffer.append((char) i);
 153  
                 }
 154  0
                 while (i != 28);        
 155  0
                 return stringbuffer.toString();
 156  
         }
 157  
     
 158  
     
 159  
     
 160  
         /** 
 161  
          * Given a string that contains HL7 messages, and possibly other junk, 
 162  
          * returns an array of the HL7 messages.  
 163  
          * An attempt is made to recognize segments even if there is other 
 164  
          * content between segments, for example if a log file logs segments 
 165  
          * individually with timestamps between them.  
 166  
          * 
 167  
          * @param theSource a string containing HL7 messages 
 168  
          * @return the HL7 messages contained in theSource
 169  
          */
 170  
         public static String[] getHL7Messages(String theSource) {
 171  0
                 List<String> messages = new ArrayList<String>(20); 
 172  0
                 Pattern startPattern = Pattern.compile("^MSH", Pattern.MULTILINE);
 173  0
                 Matcher startMatcher = startPattern.matcher(theSource);
 174  
 
 175  0
                 while (startMatcher.find()) {
 176  0
                         String messageExtent = 
 177  
                                 getMessageExtent(theSource.substring(startMatcher.start()), startPattern);
 178  
                         
 179  0
                         char fieldDelim = messageExtent.charAt(3);
 180  0
                         Pattern segmentPattern = Pattern.compile("^[A-Z\\d]{3}\\" + fieldDelim + ".*$", Pattern.MULTILINE);
 181  0
                         Matcher segmentMatcher = segmentPattern.matcher(messageExtent);
 182  0
                         StringBuffer msg = new StringBuffer();
 183  0
                         while (segmentMatcher.find()) {
 184  0
                                 msg.append(segmentMatcher.group().trim());
 185  0
                                 msg.append('\r');
 186  
                         }
 187  0
                         messages.add(msg.toString());
 188  0
                 }
 189  0
                 return messages.toArray(new String[0]);
 190  
         }
 191  
     
 192  
         /** 
 193  
          * Given a string that contains at least one HL7 message, returns the 
 194  
          * smallest string that contains the first of these messages.  
 195  
          */
 196  
         private static String getMessageExtent(String theSource, Pattern theStartPattern) {
 197  0
                 Matcher startMatcher = theStartPattern.matcher(theSource);
 198  0
                 if (!startMatcher.find()) {
 199  0
                         throw new IllegalArgumentException(theSource + "does not contain message start pattern" 
 200  
                                 + theStartPattern.toString());
 201  
                 }
 202  
             
 203  0
                 int start = startMatcher.start();
 204  0
                 int end = theSource.length();
 205  0
                 if (startMatcher.find()) {
 206  0
                         end = startMatcher.start();
 207  
                 }
 208  
          
 209  0
                 return theSource.substring(start, end).trim();
 210  
         }
 211  
     
 212  
     
 213  
     private void sendMessage(String theMessage) throws IOException
 214  
     {
 215  0
         os.write( HL7_START_OF_MESSAGE.getBytes() );
 216  0
         os.write( theMessage.getBytes() );
 217  0
         os.write( HL7_END_OF_MESSGAE.getBytes() );
 218  0
         os.write(13);
 219  0
         os.flush();
 220  0
         ourLog.info("Sent: " + theMessage);
 221  0
     }
 222  
      
 223  
     
 224  
     
 225  
     /**
 226  
      * Main method for running the application
 227  
      * 
 228  
      * example command lines args:
 229  
      * 
 230  
      * -f UHN_PRO_DEV_PATIENTS.dat -h 142.224.178.152 -p 3999
 231  
      * 
 232  
      */
 233  
     public static void main( String[] theArgs ) {
 234  
 
 235  
         //parse command line arguments        
 236  
 
 237  
         //create the command line parser
 238  0
         CommandLineParser parser = new PosixParser();
 239  
 
 240  
         //create the Options
 241  0
         Options options = new Options();
 242  
 
 243  0
         options.addOption("h", "host", true, "IP of host to send to");
 244  0
         options.addOption("p", "port", true, "port to send to");
 245  0
         options.addOption("f", "file", true, "file to read HL7 messages from");
 246  
         
 247  0
         CommandLine cmdLine = null;
 248  
         try
 249  
         {
 250  
             // parse the command line arguments
 251  0
             cmdLine = parser.parse(options, theArgs);
 252  
         }
 253  0
         catch (ParseException e)
 254  
         {
 255  0
             ourLog.error(e.getMessage(), e);
 256  0
             return;
 257  0
         }
 258  
 
 259  0
         String portString = cmdLine.getOptionValue("p");
 260  0
         int port = 0;
 261  0
         String host = cmdLine.getOptionValue("h");        
 262  0
         String file = cmdLine.getOptionValue("f");
 263  
         
 264  0
         if (portString == null || host == null || file == null)
 265  
         {
 266  
             //automatically generate the help statement
 267  0
             HelpFormatter formatter = new HelpFormatter();
 268  
             //assuming that a shell script named serverTest will be created
 269  0
             formatter.printHelp( "serverTest", options );
 270  0
             return;
 271  
         }
 272  
         else {
 273  
             //parse portAsString
 274  0
             port = Integer.parseInt(portString);
 275  
         }
 276  
         
 277  0
         HL7ServerTestHelper serverTest = new HL7ServerTestHelper( host, port );
 278  
         
 279  
         //InputStream msgInputStream = HL7ServerTestHelper.class.getResourceAsStream( file );
 280  0
                 InputStream msgInputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(file);                
 281  
         try{            
 282  0
             serverTest.openSocket();
 283  0
             serverTest.process( msgInputStream );
 284  
         }
 285  0
         catch(Exception e){
 286  0
                 e.printStackTrace();
 287  0
             HelpFormatter formatter = new HelpFormatter();
 288  
             //assuming that a shell script named hl7mom will be created
 289  0
             formatter.printHelp( "serverTest", options );
 290  0
             System.exit(-1);
 291  0
         }
 292  
         
 293  0
         serverTest.closeSocket();
 294  0
     }
 295  
     
 296  
         /**
 297  
          * TODO: this code is copied from HAPI ... should make it part of HAPI public API instead
 298  
          * Removes C and C++ style comments from a reader stream.  C style comments are
 299  
          * distinguished from URL protocol delimiters by the preceding colon in the
 300  
          * latter.
 301  
          */
 302  
         public static class CommentFilterReader extends PushbackReader {
 303  
         
 304  0
                 private final char[] startCPPComment = {'/', '*'};
 305  0
                 private final char[] endCPPComment = {'*', '/'};
 306  0
                 private final char[] startCComment = {'/', '/'};
 307  0
                 private final char[] endCComment = {'\n'};
 308  0
                 private final char[] protocolDelim = {':', '/', '/'};
 309  
         
 310  
                 public CommentFilterReader(Reader in) {
 311  0
                         super(in, 5);
 312  0
                 }
 313  
         
 314  
                 /**
 315  
                  * Returns the next character, not including comments.
 316  
                  */
 317  
                 public int read() throws IOException {
 318  0
                         if (atSequence(protocolDelim)) {
 319  
                                 //proceed normally
 320  0
                         } else if (atSequence(startCPPComment)) {
 321  
                                 //skip() doesn't seem to work for some reason
 322  0
                                 while (!atSequence(endCPPComment)) super.read();
 323  0
                                 for (int i = 0; i < endCPPComment.length; i++) super.read();
 324  0
                         } else if (atSequence(startCComment)) {
 325  0
                                 while (!atSequence(endCComment)) super.read();
 326  0
                                 for (int i = 0; i < endCComment.length; i++) super.read();
 327  
                         }
 328  0
                         int ret = super.read();
 329  0
                         if (ret == 65535) ret = -1;
 330  0
                         return ret;            
 331  
                 }
 332  
                 
 333  
                 public int read(char[] cbuf, int off, int len) throws IOException {
 334  0
                         int i = -1;
 335  0
                         boolean done = false;
 336  0
                         while (++i < len) {
 337  0
                                 int next = read();
 338  0
                                 if (next == 65535 || next == -1) { //Pushback causes -1 to convert to 65535
 339  0
                                         done = true;
 340  0
                                         break;  
 341  
                                 }
 342  0
                                 cbuf[off + i] = (char) next;
 343  0
                         }
 344  0
                         if (i == 0 && done) i = -1; 
 345  0
                         return i; 
 346  
                 }            
 347  
         
 348  
                 /**
 349  
                  * Tests incoming data for match with char sequence, resets reader when done.
 350  
                  */
 351  
                 private boolean atSequence(char[] sequence) throws IOException {
 352  0
                         boolean result = true;
 353  0
                         int i = -1;
 354  0
                         int[] data = new int[sequence.length];
 355  0
                         while (++i < sequence.length && result == true) {
 356  0
                                 data[i] = super.read();
 357  0
                                 if ((char) data[i] != sequence[i]) result = false; //includes case where end of stream reached
 358  
                         }
 359  0
                         for (int j = i-1; j >= 0; j--) {
 360  0
                                 this.unread(data[j]);
 361  
                         }
 362  0
                         return result;
 363  
                 }        
 364  
         }
 365  
     
 366  
 
 367  
 }