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 }