| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| Receiver |
|
| 2.3333333333333335;2.333 | ||||
| Receiver$Grunt |
|
| 2.3333333333333335;2.333 |
| 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 "Receiver.java". Description: | |
| 10 | * "Listens for incoming messages on a certain input stream, and | |
| 11 | * sends them to the appropriate location." | |
| 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.IOException; | |
| 31 | import java.net.SocketException; | |
| 32 | ||
| 33 | import org.slf4j.Logger; | |
| 34 | import org.slf4j.LoggerFactory; | |
| 35 | ||
| 36 | import ca.uhn.hl7v2.concurrent.Service; | |
| 37 | import ca.uhn.hl7v2.llp.HL7Reader; | |
| 38 | ||
| 39 | /** | |
| 40 | * Listens for incoming messages on a certain input stream, and sends them to | |
| 41 | * the appropriate location. | |
| 42 | * | |
| 43 | * @author Bryan Tripp | |
| 44 | */ | |
| 45 | 10 | public class Receiver extends Service { |
| 46 | ||
| 47 | 5 | private static final Logger log = LoggerFactory.getLogger(Receiver.class); |
| 48 | ||
| 49 | private ActiveConnection conn; | |
| 50 | private HL7Reader in; | |
| 51 | ||
| 52 | /** Creates a new instance of Receiver, associated with the given Connection */ | |
| 53 | public Receiver(ActiveConnection c, HL7Reader in) { | |
| 54 | 543 | super("Receiver", c.getExecutorService()); |
| 55 | 543 | this.conn = c; |
| 56 | 543 | this.in = in; |
| 57 | 543 | } |
| 58 | ||
| 59 | ||
| 60 | @Override | |
| 61 | protected void handle() { | |
| 62 | try { | |
| 63 | 1859 | String message = in.getMessage(); |
| 64 | 1345 | if (message == null) { |
| 65 | 134 | log.debug("Failed to read a message"); |
| 66 | } else { | |
| 67 | 1211 | processMessage(message); |
| 68 | } | |
| 69 | 499 | } catch (SocketException e) { |
| 70 | // This probably means that the client closed the server connection normally | |
| 71 | 499 | conn.close(); |
| 72 | 499 | log.info("SocketException: closing Connection from " + describeRemoteConnection() + ", will no longer read messages with this Receiver: " + e.getMessage()); |
| 73 | 0 | } catch (IOException e) { |
| 74 | 0 | conn.close(); |
| 75 | 0 | log.warn("IOException: closing Connection from " + describeRemoteConnection() + ", will no longer read messages with this Receiver. ", e); |
| 76 | 10 | } catch (Exception e) { |
| 77 | 10 | conn.close(); |
| 78 | 10 | log.error("Unexpected error, closing connection from " + describeRemoteConnection() + " - ", e); |
| 79 | 1844 | } |
| 80 | ||
| 81 | 1854 | } |
| 82 | ||
| 83 | ||
| 84 | private String describeRemoteConnection() { | |
| 85 | 509 | return conn.getRemoteAddress().getHostAddress() + ":" + conn.getRemotePort(); |
| 86 | } | |
| 87 | ||
| 88 | ||
| 89 | /** | |
| 90 | * Processes a single incoming message by sending it to the appropriate | |
| 91 | * internal location. If an incoming message contains an MSA-2 field, it is | |
| 92 | * assumed that this message is meant as a reply to a message that has been | |
| 93 | * sent earlier. In this case an attempt is give the message to the object | |
| 94 | * that sent the corresponding outbound message. If the message contains an | |
| 95 | * MSA-2 but there are no objects that appear to be waiting for it, it is | |
| 96 | * discarded and an exception is logged. If the message does not contain an | |
| 97 | * MSA-2 field, it is concluded that the message has arrived unsolicited. In | |
| 98 | * this case it is sent to the Responder (in a new Thread). | |
| 99 | */ | |
| 100 | protected void processMessage(String message) { | |
| 101 | 1211 | String ackID = conn.getParser().getAckID(message); |
| 102 | 1211 | if (ackID == null) { |
| 103 | 633 | log.debug("Unsolicited Message Received: {}", message); |
| 104 | 633 | getExecutorService().submit(new Grunt(conn, message)); |
| 105 | } else { | |
| 106 | 578 | if (!conn.isRecipientWaiting(ackID, message)) { |
| 107 | 0 | log.info("Unexpected Message Received. This message appears to be an acknowledgement (MSA-2 has a value) so it will be ignored: {}", message); |
| 108 | } else { | |
| 109 | 578 | log.debug("Response Message Received: {}", message); |
| 110 | } | |
| 111 | } | |
| 112 | 1211 | } |
| 113 | ||
| 114 | /** Independent thread for processing a single message */ | |
| 115 | private static class Grunt implements Runnable { | |
| 116 | ||
| 117 | private ActiveConnection conn; | |
| 118 | private String m; | |
| 119 | ||
| 120 | 633 | public Grunt(ActiveConnection conn, String message) { |
| 121 | 633 | this.conn = conn; |
| 122 | 633 | this.m = message; |
| 123 | 633 | } |
| 124 | ||
| 125 | public void run() { | |
| 126 | try { | |
| 127 | 633 | String response = conn.getResponder().processMessage(m); |
| 128 | 633 | if (response != null) { |
| 129 | 623 | conn.getAckWriter().writeMessage(response); |
| 130 | } else { | |
| 131 | 10 | log.debug("Not responding to incoming message"); |
| 132 | } | |
| 133 | 0 | } catch (Exception e) { |
| 134 | 0 | log.error("Error while processing message: ", e); |
| 135 | 633 | } |
| 136 | 633 | } |
| 137 | } | |
| 138 | ||
| 139 | } |