Coverage Report - ca.uhn.hl7v2.app.AcceptorThread
 
Classes in this File Line Coverage Branch Coverage Complexity
AcceptorThread
72%
32/44
70%
7/10
2.5
AcceptorThread$AcceptedSocket
83%
5/6
50%
1/2
2.5
 
 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 "AcceptorThread.java".  Description: 
 10  
 "A TCP/IP-based HL7 Service that uses separate ports for inbound and outbound messages." 
 11  
 
 12  
 The Initial Developer of the Original Code is University Health Network. Copyright (C) 
 13  
 2001.  All Rights Reserved. 
 14  
 
 15  
 Contributor(s): ______________________________________. 
 16  
 
 17  
 Alternatively, the contents of this file may be used under the terms of the 
 18  
 GNU General Public License (the "GPL"), in which case the provisions of the GPL are 
 19  
 applicable instead of those above.  If you wish to allow use of your version of this 
 20  
 file only under the terms of the GPL and not to allow others to use your version 
 21  
 of this file under the MPL, indicate your decision by deleting  the provisions above 
 22  
 and replace  them with the notice and other provisions required by the GPL License.  
 23  
 If you do not delete the provisions above, a recipient may use your version of 
 24  
 this file under either the MPL or the GPL. 
 25  
  */
 26  
 package ca.uhn.hl7v2.app;
 27  
 
 28  
 import java.io.IOException;
 29  
 import java.net.InetSocketAddress;
 30  
 import java.net.ServerSocket;
 31  
 import java.net.Socket;
 32  
 import java.net.SocketException;
 33  
 import java.net.SocketTimeoutException;
 34  
 import java.util.concurrent.BlockingQueue;
 35  
 import java.util.concurrent.ExecutorService;
 36  
 
 37  
 import org.slf4j.Logger;
 38  
 import org.slf4j.LoggerFactory;
 39  
 
 40  
 import ca.uhn.hl7v2.concurrent.Service;
 41  
 import ca.uhn.hl7v2.util.SocketFactory;
 42  
 import ca.uhn.hl7v2.util.StandardSocketFactory;
 43  
 
 44  
 /**
 45  
  * A Runnable that accepts connections on a ServerSocket and adds them to a
 46  
  * {@link BlockingQueue}, so that they can be handled asynchronously. After
 47  
  * stop() is called, the ServerSocket is closed.
 48  
  */
 49  
 class AcceptorThread extends Service {
 50  
 
 51  
         static final int TIMEOUT = 500;
 52  1
         private static final Logger log = LoggerFactory
 53  
                         .getLogger(AcceptorThread.class);
 54  
         private int port;
 55  21
         private boolean tls = false;
 56  
         private ServerSocket ss;
 57  
         private final BlockingQueue<AcceptedSocket> queue;
 58  
         private final SocketFactory socketFactory;
 59  
 
 60  
         public AcceptorThread(ServerSocket serverSocket, int port, ExecutorService service,
 61  
                         BlockingQueue<AcceptedSocket> queue) throws IOException,
 62  
                         SocketException {
 63  0
                 this(port, false, service, queue);
 64  0
                 this.ss = serverSocket;
 65  0
         }
 66  
 
 67  
         public AcceptorThread(int port, ExecutorService service,
 68  
                         BlockingQueue<AcceptedSocket> queue) throws IOException,
 69  
                         SocketException {
 70  0
                 this(port, false, service, queue);
 71  0
         }
 72  
 
 73  
         public AcceptorThread(int port, boolean tls, ExecutorService service,
 74  
                         BlockingQueue<AcceptedSocket> queue) throws IOException,
 75  
                         SocketException {
 76  2
                 this(port, tls, service, queue, null);
 77  2
         }
 78  
 
 79  
         public AcceptorThread(int port, boolean tls, ExecutorService service, BlockingQueue<AcceptedSocket> queue, SocketFactory socketFactory) {
 80  21
                 super("Socket Acceptor", service);
 81  21
                 this.port = port;
 82  21
                 this.queue = queue;
 83  21
                 this.tls = tls;
 84  21
                 if (socketFactory == null) {
 85  2
                         socketFactory = new StandardSocketFactory();
 86  
                 }
 87  21
                 this.socketFactory = socketFactory;
 88  21
         }
 89  
 
 90  
         @Override
 91  
         protected void afterStartup() {
 92  
                 try {
 93  21
                         if (this.tls) {
 94  0
                                 ss = socketFactory.createTlsServerSocket();
 95  
                         } else {
 96  21
                                 ss = socketFactory.createServerSocket();
 97  
                         }
 98  21
                         ss.bind(new InetSocketAddress(port));
 99  21
                         ss.setSoTimeout(TIMEOUT);
 100  0
                 } catch (IOException e) {
 101  0
                         throw new RuntimeException(e);
 102  21
                 }
 103  21
         }
 104  
 
 105  
         @Override
 106  
         protected void handle() {
 107  
                 try {
 108  964
                         Socket s = ss.accept();
 109  49
                         s.setSoTimeout(TIMEOUT);
 110  49
                         if (!queue.offer(new AcceptedSocket(s))) {
 111  1
                                 log.error("Denied enqueuing server-side socket {}", s);
 112  1
                                 s.close();
 113  
                         } else
 114  48
                                 log.debug("Enqueued server-side socket {}", s);
 115  911
                 } catch (SocketTimeoutException e) { /* OK - just timed out */
 116  911
                         log.trace("No connection established in recent {} ms.", TIMEOUT);
 117  0
                 } catch (IOException e) {
 118  0
                         log.error("Error while accepting connections", e);
 119  960
                 }
 120  960
         }
 121  
 
 122  
         @Override
 123  
         protected void afterTermination() {
 124  
                 try {
 125  17
                         if (ss != null && !ss.isClosed())
 126  17
                                 ss.close();
 127  0
                 } catch (IOException e) {
 128  0
                         log.warn("Error during stopping the thread", e);
 129  17
                 }
 130  17
         }
 131  
 
 132  
         class AcceptedSocket {
 133  
                 Socket socket;
 134  
                 AcceptorThread origin;
 135  
 
 136  49
                 public AcceptedSocket(Socket socket) {
 137  49
                         if (socket == null)
 138  0
                                 throw new IllegalArgumentException("Socket must not be null");
 139  49
                         this.socket = socket;
 140  49
                         this.origin = AcceptorThread.this;
 141  49
                 }
 142  
 
 143  
         }
 144  
 
 145  
 }