Coverage Report - ca.uhn.hl7v2.protocol.impl.DualTransportConnector
 
Classes in this File Line Coverage Branch Coverage Complexity
DualTransportConnector
92%
23/25
64%
9/14
2.1
DualTransportConnector$ConnectThread
81%
9/11
N/A
2.1
 
 1  
 /*
 2  
  * Created on 20-May-2004
 3  
  */
 4  
 package ca.uhn.hl7v2.protocol.impl;
 5  
 
 6  
 import ca.uhn.hl7v2.protocol.TransportException;
 7  
 import ca.uhn.hl7v2.protocol.TransportLayer;
 8  
 
 9  
 /**
 10  
  * <p>A utility for connecting separate inbound and outbound 
 11  
  * <code>TransortLayer</code>s in a manner that avoids deadlock.</p>  
 12  
  * 
 13  
  * <p>It is not safe to call connect() on two <code>TransportLayer</code>
 14  
  * in the same thread, because it blocks, and the remote system may be doing 
 15  
  * the same thing, but in the opposite order.  This class provides a method  
 16  
  * that connects two layers in separate threads, and pends until they are
 17  
  * both connected.</p>
 18  
  * 
 19  
  * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a>
 20  
  * @version $Revision: 1.1 $ updated on $Date: 2007-02-19 02:24:26 $ by $Author: jamesagnew $
 21  
  */
 22  
 public class DualTransportConnector {
 23  
 
 24  
     private final TransportLayer myTransportA;
 25  
     private final TransportLayer myTransportB;
 26  
     private boolean isConnecting;
 27  
     
 28  
     /**
 29  
      * @param theTransportA one <code>TransportLayer</code> we will want to connect 
 30  
      * @param theTransportB another one
 31  
      */
 32  10
     public DualTransportConnector(TransportLayer theTransportA, TransportLayer theTransportB) {
 33  10
         myTransportA = theTransportA;
 34  10
         myTransportB = theTransportB;
 35  10
     }
 36  
     
 37  
     /**
 38  
      * @return one of the underlying <code>TransportLayer</code>s.  
 39  
      */
 40  
     public TransportLayer getTransportA() {
 41  10
         return myTransportA;
 42  
     }
 43  
     
 44  
     /**
 45  
      * @return the other underlying <code>TransportLayer</code>.  
 46  
      */
 47  
     public TransportLayer getTransportB() {
 48  10
         return myTransportB;
 49  
     }
 50  
     
 51  
     /**
 52  
      * Connects both <code>TransportLayer</code>s in separate threads,   
 53  
      * and returns when both have been connected, or when cancelConnect() 
 54  
      * is called. 
 55  
      */
 56  
     public void connect() throws TransportException {
 57  10
         isConnecting = true;
 58  10
         ConnectThread c1 = new ConnectThread(myTransportA);
 59  10
         ConnectThread c2 = new ConnectThread(myTransportB);
 60  10
         c1.start();
 61  10
         c2.start();
 62  
             
 63  52
         while (isConnecting 
 64  52
             && (!c1.isConnected() || !c2.isConnected())
 65  42
             && c1.getException() == null
 66  42
             && c2.getException() == null) {
 67  
                 
 68  
             try {
 69  42
                 Thread.sleep(1);
 70  42
             } catch (InterruptedException e) {}
 71  
         }
 72  
         
 73  10
         if (c1.getException() != null) throw c1.getException();
 74  10
         if (c2.getException() != null) throw c2.getException();
 75  10
     }
 76  
     
 77  
     public void disconnect() throws TransportException {
 78  10
         myTransportA.disconnect();
 79  10
         myTransportB.disconnect();
 80  10
     }
 81  
     
 82  
     /**
 83  
      * Cancels a connect() in progress.  Since connect() blocks, this must 
 84  
      * be called from a separate thread.  
 85  
      */
 86  
     public void cancelConnect() {
 87  0
         isConnecting = false;
 88  0
     }
 89  
     
 90  
     /**
 91  
      * A class to facilitate connecting a <code>TransportLayer</code> in 
 92  
      * a separate thread.  This is needed when we want to perform two connections
 93  
      * that are initiated remotely, and we don't know the order in which the 
 94  
      * remote system will initiate the connections. 
 95  
      *   
 96  
      * @author <a href="mailto:bryan.tripp@uhn.on.ca">Bryan Tripp</a>
 97  
      * @version $Revision: 1.1 $ updated on $Date: 2007-02-19 02:24:26 $ by $Author: jamesagnew $
 98  
      */
 99  
     private static class ConnectThread extends Thread {
 100  
         
 101  
         private TransportLayer myTransport;
 102  
         private TransportException myException;        
 103  
         
 104  20
         public ConnectThread(TransportLayer theTransport) {
 105  20
             myTransport = theTransport;
 106  20
         }
 107  
         
 108  
         public boolean isConnected() {
 109  70
             return myTransport.isConnected();
 110  
         }
 111  
         
 112  
         /**
 113  
          * @return an exception encountered during the last run, if any
 114  
          */
 115  
         public TransportException getException() {
 116  104
             return myException;
 117  
         }
 118  
         
 119  
         public void run() {
 120  20
             myException = null;
 121  
             try {
 122  20
                 myTransport.connect();
 123  0
             } catch (TransportException e) {
 124  0
                 myException = e;
 125  20
             }
 126  20
         }
 127  
     }
 128  
 
 129  
 }