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 "Responder.java". Description: 10 * "Performs the responding role in a message exchange according to HL7's original mode 11 * processing rules." 12 * 13 * The Initial Developer of the Original Code is University Health Network. Copyright (C) 14 * 2002. All Rights Reserved. 15 * 16 * Contributor(s): ______________________________________. 17 * 18 * Alternatively, the contents of this file may be used under the terms of the 19 * GNU General Public License (the �GPL�), in which case the provisions of the GPL are 20 * applicable instead of those above. If you wish to allow use of your version of this 21 * file only under the terms of the GPL and not to allow others to use your version 22 * of this file under the MPL, indicate your decision by deleting the provisions above 23 * and replace them with the notice and other provisions required by the GPL License. 24 * If you do not delete the provisions above, a recipient may use your version of 25 * this file under either the MPL or the GPL. 26 * 27 */ 28 package ca.uhn.hl7v2.app; 29 30 import java.io.BufferedReader; 31 import java.io.File; 32 import java.io.FileReader; 33 import java.io.PipedInputStream; 34 import java.io.PipedOutputStream; 35 import java.io.Reader; 36 import java.net.InetSocketAddress; 37 import java.net.Socket; 38 import java.util.HashMap; 39 import java.util.Map; 40 41 import ca.uhn.hl7v2.HL7Exception; 42 import ca.uhn.hl7v2.model.Message; 43 import ca.uhn.hl7v2.parser.Parser; 44 import ca.uhn.hl7v2.parser.PipeParser; 45 import ca.uhn.hl7v2.protocol.ApplicationRouter; 46 import ca.uhn.hl7v2.protocol.Transportable; 47 import ca.uhn.hl7v2.protocol.impl.TransportableImpl; 48 49 /** 50 * <p> 51 * Performs the responding role in a message exchange (i.e receiver of the first 52 * message, sender of the response; analagous to the server in a client-server 53 * interaction), according to HL7's original mode processing rules. 54 * </p> 55 * <p> 56 * At the time of writing, enhanced mode, two-phase reply, continuation 57 * messages, and batch processing are unsupported. 58 * </p> 59 * 60 * @author Bryan Tripp 61 */ 62 class Responder { 63 64 private ApplicationRouter apps; 65 private final Socket inboundSocket; 66 67 /** 68 * Creates a new instance of Responder 69 */ 70 public Responder(Socket theInboundSocket) { 71 inboundSocket = theInboundSocket; 72 } 73 74 75 /** 76 * Processes an incoming message string and returns the response message 77 * string. Message processing consists of parsing the message, finding an 78 * appropriate Application and processing the message with it, and encoding 79 * the response. Applications are chosen from among those registered using 80 * <code>registerApplication</code>. The Parser is obtained from the 81 * Connection associated with this Responder. 82 */ 83 protected String processMessage(String incomingMessageString) 84 throws HL7Exception { 85 86 Map<String, Object> metadata = new HashMap<>(); 87 InetSocketAddress remoteSocketAddress = (InetSocketAddress) inboundSocket.getRemoteSocketAddress(); 88 metadata.put(ApplicationRouter.METADATA_KEY_SENDING_IP, remoteSocketAddress.getAddress().getHostAddress()); 89 metadata.put(ApplicationRouter.METADATA_KEY_SENDING_PORT, remoteSocketAddress.getPort()); 90 91 Transportable response = apps.processMessage(new TransportableImpl(incomingMessageString, metadata)); 92 return response.getMessage(); 93 } 94 95 // /** 96 // * Logs the given exception and creates an error message to send to the 97 // * remote system. 98 // * 99 // * @param encoding 100 // * The encoding for the error message. If <code>null</code>, uses 101 // * default encoding 102 // */ 103 // public static String logAndMakeErrorMessage(Exception e, Segment inHeader, 104 // Parser p, String encoding) throws HL7Exception { 105 // return ApplicationRouterImpl.logAndMakeErrorMessage(e, inHeader, p, encoding); 106 // } 107 108 /** 109 * Registers an Application with this Responder. The "Application", in this 110 * context, is the software that uses the information in the message. If 111 * multiple applications are registered, incoming Message objects will be 112 * passed to each one in turn (calling <code>canProcess()</code>) until one 113 * of them accepts responsibility for the message. If none of the registered 114 * applications can process the message, a DefaultApplication is used, which 115 * simply returns an Application Reject message. 116 */ 117 void setApplicationRouter(ApplicationRouter router) { 118 this.apps = router; 119 } 120 121 /** 122 * Test code. 123 */ 124 @SuppressWarnings({ "unused", "resource" }) 125 public static void main(String[] args) { 126 if (args.length != 1) { 127 System.err.println("Usage: DefaultApplication message_file"); 128 System.exit(1); 129 } 130 131 // read test message file ... 132 try { 133 File messageFile = new File(args[0]); 134 Reader in = new BufferedReader(new FileReader(messageFile)); 135 int fileLength = (int) messageFile.length(); 136 char[] cbuf = new char[fileLength]; 137 in.read(cbuf, 0, fileLength); 138 String messageString = new String(cbuf); 139 140 // parse inbound message ... 141 final Parser parser = new PipeParser(); 142 Message inMessage = null; 143 try { 144 inMessage = parser.parse(messageString); 145 } catch (HL7Exception e) { 146 e.printStackTrace(); 147 } 148 149 // process with responder ... 150 PipedInputStream initInbound = new PipedInputStream(); 151 PipedOutputStream initOutbound = new PipedOutputStream(); 152 PipedInputStream respInbound = new PipedInputStream(initOutbound); 153 PipedOutputStream respOutbound = new PipedOutputStream(initInbound); 154 155 /* 156 * This code won't work with new changes: final ActiveInitiator init = new 157 * ActiveInitiator(parser, new MinLowerLayerProtocol(), initInbound, 158 * initOutbound); Responder resp = new Responder(respInbound, 159 * respOutbound); 160 * 161 * //run the initiator in a separate thread ... final Message 162 * inMessCopy = inMessage; Thread initThd = new Thread(new 163 * Runnable() { public void run() { try { Message response = 164 * init.sendAndReceive(inMessCopy); 165 * System.out.println("This is initiator writing response ..."); 166 * System.out.println(parser.encode(response)); } catch (Exception 167 * ie) { if (HL7Exception.class.isAssignableFrom(ie.getClass())) { 168 * System.out.println("Error in segment " + 169 * ((HL7Exception)ie).getSegmentName() + " field " + 170 * ((HL7Exception)ie).getFieldPosition()); } ie.printStackTrace(); } 171 * } }); initThd.start(); 172 * 173 * //process the message we expect from the initiator thread ... 174 * System.out.println("Responder is going to respond now ..."); 175 * resp.processOneMessage(); 176 */ 177 } catch (Exception e) { 178 e.printStackTrace(); 179 } 180 181 } 182 183 184 }