50. EPMO Open Source Coordination Office Redaction File Detail Report

Produced by Araxis Merge on 6/5/2018 10:24:14 AM Central Daylight Time. See www.araxis.com for information about Merge. This report uses XHTML and CSS2, and is best viewed with a modern standards-compliant browser. For optimum results when printing this report, use landscape orientation and enable printing of background images and colours in your browser.

50.1 Files compared

# Location File Last Modified
1 patch_205_build_9.zip\Java\VistaConnection\main\src\java\gov\va\med\imaging\url\vista VistaConnection.java Wed May 30 14:35:27 2018 UTC
2 patch_205_build_9.zip\Java\VistaConnection\main\src\java\gov\va\med\imaging\url\vista VistaConnection.java Mon Jun 4 20:34:41 2018 UTC

50.2 Comparison summary

Description Between
Files 1 and 2
Text Blocks Lines
Unchanged 3 2250
Changed 2 4
Inserted 0 0
Removed 0 0

50.3 Comparison options

Whitespace
Character case Differences in character case are significant
Line endings Differences in line endings (CR and LF characters) are ignored
CR/LF characters Not shown in the comparison detail

50.4 Active regular expressions

No regular expressions were active.

50.5 Comparison detail

  1   /**
  2    * 
  3    */
  4   package go v.va.med.i maging.url .vista;
  5  
  6   import gov .va.med.im aging.url. vista.conf iguration. VistaConne ctionConfi guration;
  7   import gov .va.med.im aging.url. vista.enum s.VistaCon nectionTyp e;
  8   import gov .va.med.im aging.url. vista.exce ptions.Inv alidVistaC redentials Exception;
  9   import gov .va.med.im aging.url. vista.exce ptions.Vis taBrokerCo nnectionSt yleExcepti on;
  10   import gov .va.med.im aging.url. vista.exce ptions.Vis taIOExcept ion;
  11   import gov .va.med.im aging.url. vista.exce ptions.Vis taMExcepti on;
  12   import gov .va.med.im aging.url. vista.exce ptions.Vis taMethodEx ception;
  13  
  14   import jav a.io.Buffe redInputSt ream;
  15   import jav a.io.IOExc eption;
  16   import jav a.io.Input Stream;
  17   import jav a.io.Input StreamRead er;
  18   import jav a.io.Outpu tStream;
  19   import jav a.io.Outpu tStreamWri ter;
  20   import jav a.io.Write r;
  21   import jav a.net.Inet Address;
  22   import jav a.net.Malf ormedURLEx ception;
  23   import jav a.net.Serv erSocket;
  24   import jav a.net.Sock et;
  25   import jav a.net.URL;
  26   import jav a.net.URLC onnection;
  27   import jav a.net.Unkn ownService Exception;
  28   import jav a.util.Col lections;
  29   import jav a.util.Has hSet;
  30   import jav a.util.Ite rator;
  31   import jav a.util.Set ;
  32   import jav a.util.Tim er;
  33   import jav a.util.Tim erTask;
  34   import jav a.util.con current.Ti meUnit;
  35   import jav a.util.con current.lo cks.Reentr antLock;
  36  
  37   import org .apache.lo gging.log4 j.LogManag er;
  38   import org .apache.lo gging.log4 j.Logger;
  39  
  40   /**
  41    * Package : MAG - Vi stA Imagin g
  42    * WARNING : Per VHA  Directive  2004-038,  this routi ne should  not be mod ified.
  43    * Date Cr eated: 07J an2008
  44    * Site Na me:  Washi ngton OI F ield Offic e, Silver  Spring, MD
  45    * @author   PI I
  46    * @versio n 1.0
  47    * 
  48    * The URL Connection  derived c lass that  is the rep resentatio n of a
  49    * connect ion to a V ista serve r. The URL  must begi n with "vi sta", the  host must
  50    * be spec ified, the  port is o ptional. A ny path in formation  is ignored .
  51    * 
  52    * Quoted  comments i n this cod e come fro m:
  53    * @see ht tp://java. sun.com/de veloper/on lineTraini ng/protoco lhandlers/
  54    * 
  55    * "The ha ndler's op enConnecti on() metho d is calle d directly  by the UR L class
  56    * openStr eam() impl ementation . An openC onnection( ) call is  a request  to the
  57    * handler  that it c reate an o bject that  can resol ve the URL  into a re source
  58    * stream.  The URLCo nnection o bject is t hat object . The name , URLConne ction,
  59    * indicat es that th e java.net .URL archi tecture de velopers e xpected th e only way
  60    * to reso lve a URL  object int o a stream  is actual ly to open  a connect ion to
  61    * some se rver, like  an HTTP o r an FTP s erver."
  62    * 
  63    */
  64   public cla ss VistaCo nnection 
  65   extends UR LConnectio n
  66   {
  67           /* *
  68            *  Default v alue for t he maximum  time to w ait during  the disco nnect conv ersation. 
  69            * /
  70           pr ivate stat ic final l ong DEFAUL T_DISCONNE CT_READ_TI MEOUT = 60 000L;
  71           pr ivate stat ic final l ong DEFAUL T_CONNECT_ READ_TIMEO UT = 60000 L;
  72           pr ivate stat ic final l ong DEFAUL T_CALL_REA D_TIMEOUT  = 120000L;
  73           
  74           /* *
  75            *  The polli ng interva l for all  read() ope rations th at have a  timeout sp ecified.
  76            * /
  77           pr ivate stat ic final l ong DEFAUL T_READ_POL LING_INTER VAL = 10L;
  78           
  79           /* *
  80            *  The delay  and polli ng period  of the dis connect th read
  81            * /
  82           pr ivate stat ic final i nt DISCONN ECT_TIMER_ PERIOD = 1 0000;
  83           pr ivate stat ic final i nt DISCONN ECT_TIMER_ DELAY = 30 000;
  84           pu blic stati c final in t DEFAULT_ PORT =  PORT ;
  85           pu blic stati c final in t DEFAULT_ SOCKET_TIM EOUT = 180 000;
  86           pu blic stati c final in t DEFAULT_ CONNECTION _SOCKET_TI MEOUT = 20 000;
  87           
  88           pr ivate fina l static i nt countWi dth = 3;
  89           
  90           pr ivate stat ic final b oolean DEF AULT_NEW_S TYLE_CONNN ECTION_STY LE_ENABLED  = false;
  91           pr ivate stat ic final b oolean DEF AULT_OLD_S TYLE_CONNN ECTION_STY LE_ENABLED  = true;
  92  
  93           //  this obje ct is used  strictly  for synchr onization  so that mu ltiple
  94           //  connect()
  95           //  methods d o not happ en simulta neously, w hich seems  to confus e Vista
  96           pr ivate stat ic Reentra ntLock con nectionSyn chronizati onLock = n ew Reentra ntLock();
  97           pr ivate long  connectSy nchronizat ionMaxWait  = 10000L;
  98           
  99           pr ivate stat ic Set<Vis taConnecti on> discon nectReques ts = 
  100                    Coll ections.sy nchronized Set( new H ashSet<Vis taConnecti on>() );
  101           pr ivate stat ic Timer d isconnectT imer;
  102           st atic
  103           {
  104                    disc onnectTime r = new Ti mer("Vista Connection Disconnect ", true);
  105                    disc onnectTime r.schedule (
  106                             new Ti merTask()
  107                             {
  108                                      @Overrid e
  109                         public voi d run()
  110                         {
  111                                               disconnect ExpiredCon nections() ;
  112                         }
  113  
  114                                      // if we  are cance led then a ssure that  the conne ctions wai ting to cl ose are cl osed.  
  115                                      @Overrid e
  116                    publ ic boolean  cancel()
  117                    {
  118                                               disconnect ExpiredCon nections() ;
  119                             return  super.can cel();
  120                    }
  121                                      
  122                                      /**
  123                     * 
  124                     */
  125                    priv ate void d isconnectE xpiredConn ections()
  126                    {
  127                             Set<Vi staConnect ion> disco nnectThisI teration;
  128  
  129                             // cop y the disc onnect req uests and  work from  the copy
  130                             // thi s will fre e the disc onnectRequ ests set f or other t hreads
  131                             synchr onized(dis connectReq uests)
  132                                               {
  133                                      disconne ctThisIter ation = ne w HashSet< VistaConne ction>(dis connectReq uests);
  134                                      disconne ctRequests .clear();
  135                                               }
  136                                               try
  137                                               {
  138                                                       fo r(
  139                                                                Iter ator<Vista Connection > disconne ctRequestI ter = disc onnectThis Iteration. iterator()
  140                                                                disc onnectRequ estIter.ha sNext(); )
  141                                                       {
  142                                                                Vist aConnectio n disconne ctingConne ction = di sconnectRe questIter. next();
  143                                                                try
  144                                                                {
  145                                                                         discon nectingCon nection.in ternalDisc onnect();
  146                                                                         discon nectReques tIter.remo ve();
  147                                                                }
  148                                                                catc h(Throwabl e t)               //  since thi s thread i s the only  way the c onnections  get disco nnected
  149                                                                                                                     // it  must stay  running
  150                                                                {
  151                                                                         logger .error(t.g etMessage( ));
  152                                                                }
  153                                                       }
  154                                               }
  155                                               catch(Thro wable t2)               // since  this thre ad is the  only way t he connect ions get d isconnecte d ...
  156                                               {
  157                                                       lo gger.error (t2.getMes sage());
  158                                               }
  159                                      }
  160                             }, DIS CONNECT_TI MER_DELAY,  DISCONNEC T_TIMER_PE RIOD);             
  161           }
  162           
  163           //  ========= ========== ========== ========== ========== ========== ========== ========== ======
  164           //  Instance  Fields and  Methods
  165           //  ========= ========== ========== ========== ========== ========== ========== ========== ======
  166           
  167           pr ivate tran sient Sock et transac tionSocket ;     // t he socket  that the m ethod call s will go  across
  168           pr ivate fina l long cre ateTime;           //  the time  that the c onnection  was create d
  169           pr ivate long  connectTi me;                         // t he time th at the con nection wa s opened
  170           pr ivate Stri ng connect ingThreadN ame;    //  the threa d name tha t initiali zed the co nnection
  171           pr ivate Stac kTraceElem ent[] conn ectingStac kTrace = n ull;         // a sta ck trace a t connect  time (for  tracing un closed con nections)
  172           
  173           // private tr ansient Lo gger logge r = LogMan ager.getLo gger(Vista Connection .class.get Name());
  174           pr ivate fina l static L ogger logg er = LogMa nager.getL ogger(Vist aConnectio n.class);
  175  
  176           pr ivate bool ean prohib itUnexpect edResponde r = false;     // if  true then  the respon ding IP mu st match t he called  IP
  177           pr ivate Vist aConnectio nType vist aConnectio nType = Vi staConnect ionType.ne wStyle;
  178           pr ivate long  pollingIn terval = D EFAULT_REA D_POLLING_ INTERVAL;             // millise conds to s leep when  waiting fo r a read
  179           pr ivate long  connectRe adTimeout  = DEFAULT_ CONNECT_RE AD_TIMEOUT ; // milli seconds to  wait for  a response  from Vist A when ope ning a con nection
  180           pr ivate long  callReadT imeout = D EFAULT_CAL L_READ_TIM EOUT;        // milli seconds to  wait for  a response  from Vist A when doi ng an RPC  call
  181           pr ivate long  disconnec tReadTimeo ut = DEFAU LT_DISCONN ECT_READ_T IMEOUT;    // millise conds to w ait for a  response f rom VistA  when closi ng a conne ction
  182           
  183           pr ivate fina l boolean  newStyleCo nnectionEn abled;
  184           pr ivate fina l boolean  oldStyleCo nnectionEn abled;
  185           
  186           pr ivate bool ean failed Call = fal se;
  187  
  188           /* *
  189            *  Create a  VistaConne ction inst ance, set  the URLCon nection pr operties t o indicate  that this
  190            *  connectio n does inp ut and out put.  
  191            *  
  192            *  @param ur l
  193            * /
  194           pu blic Vista Connection (URL url)
  195           {
  196                    supe r(url);
  197                    setD oInput(tru e);
  198                    setD oOutput(tr ue);
  199                    setU seCaches(f alse);
  200                    
  201                    Long  connectio nReadTimeo utValue =  getVistaCo nnectionCo nfiguratio n().getCon nectReadTi meout();
  202                    setC onnectRead Timeout(co nnectionRe adTimeoutV alue != nu ll ? conne ctionReadT imeoutValu e : DEFAUL T_CONNECT_ READ_TIMEO UT );
  203                    
  204                    Long  callReadT imeoutValu e = getVis taConnecti onConfigur ation().ge tCallReadT imeout();
  205                    setC allReadTim eout(callR eadTimeout Value != n ull ? call ReadTimeou tValue : D EFAULT_CAL L_READ_TIM EOUT );
  206                    
  207                    Long  disconnec tReadTimeo utValue =  getVistaCo nnectionCo nfiguratio n().getDis connectRea dTimeout() ;
  208                    setD isconnectR eadTimeout (disconnec tReadTimeo utValue !=  null ? di sconnectRe adTimeoutV alue : DEF AULT_DISCO NNECT_READ _TIMEOUT ) ;
  209                    
  210                    Bool ean newSty leConnecti onValue =  getVistaCo nnectionCo nfiguratio n().getNew StyleLogin Enabled();
  211                    newS tyleConnec tionEnable d = (newSt yleConnect ionValue ! = null ? n ewStyleCon nectionVal ue : DEFAU LT_NEW_STY LE_CONNNEC TION_STYLE _ENABLED);
  212                    
  213                    Bool ean oldSty leConnecti onValue =  getVistaCo nnectionCo nfiguratio n().getOld StyleLogin Enabled();
  214                    oldS tyleConnec tionEnable d = (oldSt yleConnect ionValue ! = null ? o ldStyleCon nectionVal ue : DEFAU LT_OLD_STY LE_CONNNEC TION_STYLE _ENABLED);
  215                    
  216                    Long  readPolli ngInterval Value = ge tVistaConn ectionConf iguration( ).getReadP ollingInte rval();
  217                    setP ollingInte rval(readP ollingInte rvalValue  != null ?  readPollin gIntervalV alue : DEF AULT_READ_ POLLING_IN TERVAL);
  218                    
  219                    this .createTim e = System .currentTi meMillis() ;
  220           }
  221  
  222           /* *
  223            *  @return
  224            * /
  225           lo ng getPoll ingInterva l()
  226           {
  227                    retu rn polling Interval;
  228           }
  229           
  230           /* *
  231            *  NOTE: the  polling i nterval ca nnot be se t to less  than 10 mi lliseconds
  232            *  @param po llingInter val
  233            * /
  234           vo id setPoll ingInterva l(long pol lingInterv al)
  235           {
  236                    this .pollingIn terval = M ath.max(10 , pollingI nterval);
  237           }
  238  
  239           /* *
  240            *  @return
  241            * /
  242           pu blic long  getConnect ReadTimeou t()
  243           {
  244                    retu rn connect ReadTimeou t;
  245           }
  246           pu blic void  setConnect ReadTimeou t(long con nectReadDe lay)
  247           {
  248                    this .connectRe adTimeout  = connectR eadDelay > = 0 ? conn ectReadDel ay : 0L;
  249           }
  250           
  251           pu blic long  getCallRea dTimeout()
  252           {
  253                    retu rn callRea dTimeout;
  254           }
  255           pu blic void  setCallRea dTimeout(l ong callRe adDelay)
  256           {
  257                    this .callReadT imeout = c allReadDel ay >= 0 ?  callReadDe lay : 0L;
  258           }
  259           
  260           pu blic long  getDisconn ectReadTim eout()
  261           {
  262                    retu rn disconn ectReadTim eout;
  263           }
  264           pu blic void  setDisconn ectReadTim eout(long  disconnect ReadDelay)
  265           {
  266                    this .disconnec tReadTimeo ut = disco nnectReadD elay >= 0  ? disconne ctReadDela y : 0L;
  267           }
  268           
  269           pu blic long  getCreateT ime()
  270       {
  271           re turn creat eTime;
  272       }
  273           pu blic long  getConnect Time()
  274       {
  275           re turn conne ctTime;
  276       }
  277           pu blic Strin g getConne ctingThrea dName()
  278       {
  279           re turn conne ctingThrea dName;
  280       }
  281           pu blic Stack TraceEleme nt[] getCo nnectingSt ackTrace()
  282       {
  283           re turn conne ctingStack Trace;
  284       }
  285           
  286           //  public vo id setRemo teFlag(boo lean fRemo te) {this. fRemote =  fRemote;}
  287           //  public bo olean isRe mote() {re turn fRemo te;}
  288  
  289           /* *
  290            *  @return t he vistaCo nnectionTy pe
  291            * /
  292           pu blic Vista Connection Type getVi staConnect ionType() 
  293           {
  294                    retu rn vistaCo nnectionTy pe;
  295           }
  296  
  297           /* *
  298            *  Return tr ue if conn ected, els e return f alse.
  299            *  It is sug gested tha t isConnec ted() alwa ys be used  to evalua te
  300            *  the conne ction stat e except f or interna l methods  that know
  301            *  how to de al with th e asynchro nous disco nnect corr ectly. 
  302            * /
  303           pu blic boole an isConne cted()
  304           {
  305                    // R eturn true  if the co nnection i s connecte d and the  connection  is NOT
  306                    // i n the list  to be dis connected  asynchrono usly.
  307                    retu rn this.co nnected &&  !disconne ctRequests .contains( this);
  308           }
  309  
  310           /* *
  311            *  This meth od is sync hronized o n two sema phores:
  312            *  1.) the f irst is it s own, to  prevent a  disconnect  from taki ng place d uring a co nnect
  313            *  and vice- versa, whi ch would r oyally scr ew things  up.
  314            *  2.) the s econd is o n a shared  semaphore  to preven t multiple  threads f rom trying  to
  315            *  connect a t the same  time, whi ch Vista a pparently  does not t olerate wi th its usu al
  316            *  good humo r.
  317            *  Since we  have two l ocks we ne ed to be c ognizant o f potentia l deadlock  scenario.   As of
  318            *  now there  are none  because th e instance  lock obje ct is alwa ys acquire d before t he shared
  319            *  object.   Keep it th at way.
  320            *  
  321            *  @throws   IOExceptio n
  322            *  @see java .net.URLCo nnection#c onnect()
  323            * /
  324           @O verride
  325           pu blic synch ronized vo id connect () 
  326           th rows IOExc eption
  327           {
  328                    // i s really c onnected
  329                    if(i sConnected ())
  330                    {
  331                             logger .warn("Vis taConnecti on.connect () called  on a conne cted insta nce, ignor ing ...");
  332                             return ;
  333                    }
  334                    
  335                    sync hronized(d isconnectR equests)
  336                    {
  337                             // if  the connec tion is wa iting for  an asynchr onous disc onnect
  338                             // the n just tak e it off t he list to  be discon nected and  return.
  339                             if(Vis taConnecti on.disconn ectRequest s.contains (this))
  340                             {
  341                                      logger.w arn("Vista Connection .connect()  called on  a instanc e during a synchronou s disconne ct, recove ring conne ction.");
  342                                      VistaCon nection.di sconnectRe quests.rem ove(this);
  343                                      return;
  344                             }
  345                    }
  346  
  347                    if(!  this.noti fyListener sBeforeOpe n() )
  348                    {
  349                             logger .warn("Vis taConnecti onListener  has retur ned false  from conne ctionOpeni ng() there by prevent ing connec tion.");
  350                             return ;
  351                    }
  352                    
  353                    if(n ewStyleCon nectionEna bled)
  354                    {
  355                             try
  356                             {
  357                                      newStyle Connect();
  358                             }
  359                             catch( VistaBroke rConnectio nStyleExce ption vbcs X)
  360                             {
  361                                      logger.w arn("Attem pted to co nnect to r emote site  '" + getU RL().toStr ing() + 
  362                                                       "  with new c onnection  style, fal ling back  to old sty le: " + vb csX.getMes sage());
  363                                      oldStyle Connect();
  364                             }
  365                    }
  366                    else
  367                    {
  368                             oldSty leConnect( );
  369                    }
  370           }
  371           
  372           /* *
  373            *  Vista has  (had) a u nique mode l for inte raction.
  374            *  The initi al connect ion to Vis tA is made  on a well -known por t, the fir st
  375            *  transacti on include s a port n umber that  will be u sed for al l subseque nt
  376            *  communica tion.  For  this impl ementation  the initi al socket  is done 
  377            *  over the  "connectio nSocket" a nd subsequ ent transa ctions tak e place
  378            *  over the  "transacti onSocket".   The conn ectionSock et exists  only for t he
  379            *  time requ ired to es tablish th e connecti on.  
  380            *  This code  allows th e OS to pi ck any ope n port for  the respo nses.
  381            *  BTW, this  opens up  a security  hole in t hat anothe r host on  the networ k
  382            *  could sni ff, detect  the recei ve port, a nd simply  transmit r esponses
  383            *  before th e real ser ver.  At t he very le ast this w ill break  the client s
  384            *  but may a ctually be  usable to  display i nvalid inf ormation.
  385            *  Ironicall y, (rumor  has it tha t) the rea son that V istA uses  a separate  socket 
  386            *  for the c onnection  and the tr ansactions  is for .. . security
  387            *  
  388            *  @throws I OException
  389            * /
  390           pr ivate void  oldStyleC onnect()
  391           th rows IOExc eption
  392           {
  393                    this .vistaConn ectionType  = VistaCo nnectionTy pe.oldStyl e;
  394                    Sock et connect ionSocket  = null;          // t emporary s ocket used  for initi al VistA c ontact
  395                    Serv erSocket s erverSocke t = null;        // t emporary s erver sock et for Vis tA to cont act us at 
  396                    
  397                    // k ludge aler t!!!
  398                    // s ynchronize  on a stat ic object  to throttl e the mult iple
  399                    // c onnect cal ls to Vist a
  400                    bool ean connec tSynchLock Acquired =  false;
  401           tr y
  402           {
  403                    conn ectSynchLo ckAcquired  = 
  404                             connec tionSynchr onizationL ock.tryLoc k(getConne ctSynchron izationMax Wait(), Ti meUnit.MIL LISECONDS) ;
  405           } 
  406           ca tch (Inter ruptedExce ption e1)
  407           {
  408                    Stri ng msg = " Failed to  acquire co nnect sync hronizatio n lock, th read inter ruped whil e waiting. ";
  409                    logg er.warn("F ailed to a cquire con nect synch ronization  lock, thr ead interr uped while  waiting." );
  410                    
  411                    thro w new IOEx ception(ms g);
  412           }
  413           
  414           UR L url = th is.getURL( );
  415                    
  416                    try
  417                    {
  418                    if(! connectSyn chLockAcqu ired)
  419                             logger .warn("Fai led to acq uire conne ct synchro nization l ock in all oted time,  proceedin g anyway." );
  420                        
  421                             String  hostname  = url.getH ost();
  422                             if( ho stname ==  null || ho stname.len gth() == 0  )
  423                                      throw ne w Malforme dURLExcept ion("No ho stname pro vided when  trying to  connect.   This shou ld never b e seen.");
  424  
  425                             int po rt = url.g etPort();
  426                             if (po rt == -1)
  427                                      port = D EFAULT_POR T;
  428  
  429                             InetAd dress loca lInetAddr  = null;
  430  
  431                             InetAd dress vist aAddr = In etAddress. getByName( hostname);         //  resolve t he hostnam e to an IP  address
  432                             
  433                             logger .info("Att empting co nnection t o '" + hos tname + "( " + vistaA ddr.getHos tAddress()  + ")'.");
  434                             
  435                             connec tionSocket  = new Soc ket(vistaA ddr, port) ;          // creates  and conne cts socket  to remote  host/port
  436                             connec tionSocket .setSoTime out(DEFAUL T_CONNECTI ON_SOCKET_ TIMEOUT);
  437                             // soc ket = new  Socket(hos tname,port );
  438                             // @to do need to  implement  connect w ith IP add ress
  439                             server Socket = n ew ServerS ocket(0);               // creat e a socket  on any fr ee port
  440                                                                                                                     // thi s will bec ome the tr ansactionS ocket
  441                                                                                                                     // whe re all tra nsactions  after conn ect will o ccur
  442                             server Socket.set SoTimeout( DEFAULT_CO NNECTION_S OCKET_TIME OUT);
  443                             localI netAddr =  InetAddres s.getLocal Host();
  444                             
  445                             // bui ld a strin g that tel ls Vista w hich socke t to send
  446                             // mes sages to u s on
  447                             String Builder sb  = new Str ingBuilder ();
  448                             sb.app end("TCPco nnect^");
  449                             sb.app end(localI netAddr.ge tHostAddre ss());                                 // o ur host ad dress
  450                             sb.app end('^');
  451                             sb.app end(server Socket.get LocalPort( ));                                    // t he server  socket tha t we just  establishe d and that  VistA
  452                                                                                                                                                        // s hould resp ond to us  on
  453                             sb.app end('^');
  454  
  455                             String  responseM sg = null;
  456                             String  requestMs g = "{XWB} " + VistaQ uery.strPa ck(sb.toSt ring(), 5) ;
  457                             
  458                             // sen d the TCPC onnect mes sage to Vi stA and ge t the resp onse
  459                             transa ctionSocke t = connec tionSocket ;                     // tempora rily set t he transac tion socke t to be th e same as  the connec tion socke t
  460                             try{re sponseMsg  = internal Call(reque stMsg, get ConnectRea dTimeout() );}   // s kips sanit y checking  on connec tion state
  461                             catch( IOExceptio n ioX)
  462                             {
  463                                      try{serv erSocket.c lose();}ca tch(IOExce ption ioX2 ){}     //  eat excep tions, jus t close it
  464                                      throw io X;
  465                             } 
  466                             catch  (InvalidVi staCredent ialsExcept ion e)
  467                {
  468                                      try{serv erSocket.c lose();}ca tch(IOExce ption ioX2 ){}     //  eat excep tions, jus t close it
  469                                      throw ne w IOExcept ion("Inval id securit y credenti als: " + e .getMessag e());
  470                } 
  471                             catch  (VistaMeth odExceptio n e)
  472                {
  473                                      try{serv erSocket.c lose();}ca tch(IOExce ption ioX2 ){}     //  eat excep tions, jus t close it
  474                                      throw ne w IOExcept ion(e.getM essage());
  475                }
  476                             finall y{transact ionSocket  = null;}       // imm ediately n ull this o ut, if we  successful ly connect
  477                                                                                                            // t hen transa ctionSocke t is acqui red from s erverSocke t, else we
  478                                                                                                            // d o not want  it connec ted or ret ained.
  479                             
  480                             try
  481                {
  482                         // VistA s hould resp ond with a n accept o n our conn ection soc ket
  483                         if( respon seMsg == n ull || !re sponseMsg. equals("ac cept") )
  484                         {
  485                             String  msg = "Co nnection n ot accepte d by '" +  hostname +  "'."; 
  486                             logger .warn(msg) ;
  487                             throw  new VistaI OException (msg);
  488                         }
  489                        
  490                         // there m ust be a d elay here  until Vist A creates  a socket
  491                         // and att empts to c onnect to  us
  492                         transactio nSocket =  serverSock et.accept( );
  493                         transactio nSocket.se tSoTimeout (DEFAULT_S OCKET_TIME OUT);
  494                        
  495                         // the hos t that we  connect to  must be t he remote  host of th e
  496                         // initial  socket co nnection,  else there  may be a  security
  497                         // problem  (man in t he middle  or simply  a sniffer)
  498                         InetAddres s remoteAd dress = tr ansactionS ocket.getI netAddress ();
  499                         if( ! vist aAddr.getH ostAddress ().equals( remoteAddr ess.getHos tAddress() ) )
  500                         {
  501                             String  msg = "Li stener soc ket connec ted to '"  + remoteAd dress.getH ostAddress () + 
  502                                      "' and s hould have  connected  to '" + v istaAddr.g etHostAddr ess() + "' .";
  503                             
  504                             if(isP rohibitUne xpectedRes ponder())
  505                             {
  506                                      msg += " Connection  will be d ropped bec ause of po tential se curity imp lications. ";
  507                                      logger.e rror(msg);
  508                                      
  509                                                       tr y{serverSo cket.close ();}catch( Throwable  t1){} // e at excepti ons, just  close it
  510                                                       tr y{transact ionSocket. close();}c atch(Throw able t2){}     // eat  exception s, just cl ose it
  511           
  512                                      throw ne w VistaIOE xception(m sg);
  513                             }
  514                             else
  515                             {
  516                                      msg += " Connection  is allowe d to conti nue despit e potentia l security  implicati ons.";
  517                                      logger.w arn(msg);
  518                             }
  519                                      
  520                         }
  521                        
  522                         // we are  now validl y connecte d to VistA
  523                             // rec ord connec tion stats  to use fo r debuggin g,
  524                         // mark ou rselves as  connected  and add o urselves t o the open Connection s list
  525                         // for mon itoring
  526                             connec tingThread Name = Thr ead.curren tThread(). getName();
  527                             connec tTime = Sy stem.curre ntTimeMill is();
  528                             connec tingStackT race = Thr ead.curren tThread(). getStackTr ace();
  529                    conn ected = tr ue;
  530                } 
  531                             catch  (VistaIOEx ception vi oX)
  532                {
  533                                      // if we  got an er ror either  in the Vi stA respon se or in v alidating
  534                                      // the r emote host , close ev erything d own
  535                    try{ transactio nSocket.cl ose();}cat ch(Throwab le t){}      // eat e xceptions,  just clos e it
  536                                      throw vi oX;
  537                }
  538                             finall y
  539                             {
  540                                      // regar dless of t he connect ion succes s, we no l onger use  the
  541                                      // conne ction sock et or the  server soc ket so clo se them
  542                    try{ connection Socket.clo se();}catc h(Throwabl e t){}       // eat e xceptions,  just clos e it
  543                    try{ serverSock et.close() ;}catch(Th rowable t) {}           // eat e xceptions,  just clos e it
  544                             }
  545                    }
  546                    fina lly
  547                    {
  548                             if(con nectionSyn chronizati onLock.isH eldByCurre ntThread() )
  549                                      connecti onSynchron izationLoc k.unlock() ;
  550                    }
  551                    this .notifyLis tenersAfte rOpen();
  552           }
  553           
  554           /* *
  555            *  
  556            *  @throws I OException
  557            *  @throws V istaBroker Connection StyleExcep tion
  558            * /
  559           pr ivate void  newStyleC onnect()
  560           th rows IOExc eption, Vi staBrokerC onnectionS tyleExcept ion
  561           {
  562                    this .vistaConn ectionType  = VistaCo nnectionTy pe.newStyl e;
  563                    Sock et connect ionSocket  = null;          // t emporary s ocket used  for initi al VistA c ontact 
  564                    
  565                    // k ludge aler t!!!
  566                    // s ynchronize  on a stat ic object  to throttl e the mult iple
  567                    // c onnect cal ls to Vist a
  568                    bool ean connec tSynchLock Acquired =  false;
  569           tr y
  570           {
  571                    conn ectSynchLo ckAcquired  = 
  572                             connec tionSynchr onizationL ock.tryLoc k(getConne ctSynchron izationMax Wait(), Ti meUnit.MIL LISECONDS) ;
  573           } 
  574           ca tch (Inter ruptedExce ption e1)
  575           {
  576                    Stri ng msg = " Failed to  acquire co nnect sync hronizatio n lock, th read inter ruped whil e waiting. ";
  577                    logg er.warn("F ailed to a cquire con nect synch ronization  lock, thr ead interr uped while  waiting." );
  578                    
  579                    thro w new IOEx ception(ms g);
  580           }
  581           
  582           UR L url = th is.getURL( );
  583                    
  584                    try
  585                    {
  586                    if(! connectSyn chLockAcqu ired)
  587                             logger .warn("Fai led to acq uire conne ct synchro nization l ock in all oted time,  proceedin g anyway." );
  588                        
  589                             String  hostname  = url.getH ost();
  590                             if( ho stname ==  null || ho stname.len gth() == 0  )
  591                                      throw ne w Malforme dURLExcept ion("No ho stname pro vided when  trying to  connect.   This shou ld never b e seen.");
  592  
  593                             int po rt = url.g etPort();
  594                             if (po rt == -1)
  595                                      port = D EFAULT_POR T;
  596  
  597                             InetAd dress loca lInetAddr  = null;
  598  
  599                             InetAd dress vist aAddr = In etAddress. getByName( hostname);         //  resolve t he hostnam e to an IP  address
  600                             
  601                             logger .info("Att empting co nnection t o '" + hos tname + "( " + vistaA ddr.getHos tAddress()  + ")'.");
  602                             
  603                             connec tionSocket  = new Soc ket(vistaA ddr, port) ;          // creates  and conne cts socket  to remote  host/port
  604                             connec tionSocket .setSoTime out(DEFAUL T_CONNECTI ON_SOCKET_ TIMEOUT);
  605  
  606                             localI netAddr =  InetAddres s.getLocal Host();
  607                             
  608                             // bui ld a strin g that tel ls Vista w hich socke t to send
  609                             // mes sages to u s on
  610                             String Builder sb  = new Str ingBuilder ();
  611                             sb.app end(VistaC onnectionT ype.newSty le.getPref ix());
  612                             sb.app end("10");
  613                             sb.app end(countW idth);
  614                             sb.app end("0");
  615                             sb.app end("4");
  616                             sb.app end((char) 10);
  617                             sb.app end("TCPCo nnect50");
  618                             sb.app end(VistaQ uery.strPa ck(localIn etAddr.get HostAddres s(), count Width));
  619                             sb.app end("f0");
  620                             sb.app end(VistaQ uery.strPa ck("0", co untWidth)) ;
  621                             sb.app end("f0");
  622                             sb.app end(VistaQ uery.strPa ck(localIn etAddr.get HostName() , countWid th));
  623                             sb.app end("f");
  624                             sb.app end((char) 4);
  625                             
  626                             String  responseM sg = null;
  627                             String  requestMs g = sb.toS tring();
  628                             
  629                             // sen d the TCPC onnect mes sage to Vi stA and ge t the resp onse
  630                             transa ctionSocke t = connec tionSocket ;                     // tempora rily set t he transac tion socke t to be th e same as  the connec tion socke t
  631                             try
  632                             {
  633                                      //System .out.print ln("Reques t message:  '" + requ estMsg + " '.");
  634                                      response Msg = inte rnalCall(r equestMsg,  getConnec tReadTimeo ut());
  635                             }        // skips  sanity ch ecking on  connection  state
  636                             catch( IOExceptio n ioX)
  637                             {                
  638                                      try{tran sactionSoc ket.close( );}catch(I OException  ioX2){}         // e at excepti ons, just  close it
  639                                      throw io X;
  640                             } 
  641                             catch  (InvalidVi staCredent ialsExcept ion e)
  642                {   
  643                                      try{tran sactionSoc ket.close( );}catch(I OException  ioX2){}         // e at excepti ons, just  close it
  644                                      // if we  got here  on the ini tial conne ct, this i ndicates t he remote  site does  not suppor t the new  style conn ector
  645                                      // throw  the appro priate exc eption
  646                                      throw ne w VistaBro kerConnect ionStyleEx ception("E rror conne cting to V istA site  '" + hostn ame + ":"  + port + " ' with new  broker st yle");
  647                } 
  648                             catch  (VistaMeth odExceptio n e)
  649                {
  650                                      try{tran sactionSoc ket.close( );}catch(I OException  ioX2){}         // e at excepti ons, just  close it
  651                                      throw ne w IOExcept ion(e.getM essage());
  652                }
  653                             finall y
  654                             {
  655                                      // immed iately nul l this out , if we su ccessfully  connect
  656                                      transact ionSocket  = null;
  657                             }        
  658                             // the n transact ionSocket  is acquire d from ser verSocket,  else we
  659                             // do  not want i t connecte d or retai ned.
  660                             
  661                             try
  662                {
  663                         // VistA s hould resp ond with a n accept o n our conn ection soc ket
  664                         if( respon seMsg == n ull || !re sponseMsg. equals("ac cept") )
  665                         {
  666                             String  msg = "Co nnection n ot accepte d by '" +  hostname +  "', respo nse was '"  + respons eMsg + "'. "; 
  667                             logger .warn(msg) ;
  668                             throw  new VistaI OException (msg);
  669                         }
  670                        
  671                         // there m ust be a d elay here  until Vist A creates  a socket
  672                         // and att empts to c onnect to  us
  673                         transactio nSocket =  connection Socket;
  674                         transactio nSocket.se tSoTimeout (DEFAULT_S OCKET_TIME OUT);
  675                        
  676                         // we are  now validl y connecte d to VistA
  677                             // rec ord connec tion stats  to use fo r debuggin g,
  678                         // mark ou rselves as  connected  and add o urselves t o the open Connection s list
  679                         // for mon itoring
  680                             connec tingThread Name = Thr ead.curren tThread(). getName();
  681                             connec tTime = Sy stem.curre ntTimeMill is();
  682                             connec tingStackT race = Thr ead.curren tThread(). getStackTr ace();
  683                    conn ected = tr ue;
  684                } 
  685                             catch  (VistaIOEx ception vi oX)
  686                {
  687                                      // if we  got an er ror either  in the Vi stA respon se or in v alidating
  688                                      // the r emote host , close ev erything d own
  689                    try{ transactio nSocket.cl ose();}cat ch(Throwab le t){}      // eat e xceptions,  just clos e it
  690                                      throw vi oX;
  691                }
  692                             finall y
  693                             {
  694                                      // for n ew style,  don't clos e the sock et since w e only use  one now.
  695                             }
  696                    }
  697                    fina lly
  698                    {
  699                             if(con nectionSyn chronizati onLock.isH eldByCurre ntThread() )
  700                                      connecti onSynchron izationLoc k.unlock() ;
  701                    }
  702                    this .notifyLis tenersAfte rOpen();
  703           }
  704  
  705           /* *
  706            *  
  707            *  @return
  708            * /
  709           pu blic boole an isProhi bitUnexpec tedRespond er()
  710       {
  711                return p rohibitUne xpectedRes ponder ;
  712       }
  713           
  714           /* *
  715            *  Set to tr ue to thro w an excep tion of th e respondi ng server  is not the  one we se nt the req uest to.
  716            *  This usua lly works,  but some  co-located  sites mus t allow th e responde r to diffe r from the  requested
  717            *  site.
  718            *  Default i s false.
  719            *  
  720            *  @param pr ohibitUnex pectedResp onder
  721            * /
  722           pu blic void  setProhibi tUnexpecte dResponder (boolean p rohibitUne xpectedRes ponder)
  723       {
  724           th is.prohibi tUnexpecte dResponder  = prohibi tUnexpecte dResponder ;
  725       }
  726  
  727           /* *
  728        * @pa ram connec tSynchroni zationMaxW ait the co nnectSynch ronization MaxWait to  set
  729        */
  730       public  void setC onnectSync hronizatio nMaxWait(l ong connec tSynchroni zationMaxW ait)
  731       {
  732           th is.connect Synchroniz ationMaxWa it = conne ctSynchron izationMax Wait;
  733       }
  734  
  735           pr ivate long  getConnec tSynchroni zationMaxW ait()
  736       {
  737                return c onnectSync hronizatio nMaxWait;
  738       }
  739  
  740           /* *
  741            *  Call an R PC on the  Vista inst ance to wh ich we are  connected .
  742            *  
  743            *  @throws I OException  
  744            *  @throws I nvalidVist aCredentia lsExceptio
  745            *  @throws V istaMethod Exception 
  746            *  @throws V istaExcept ion 
  747            * /
  748           /*
  749           pu blic synch ronized St ring call( String req uest) 
  750           th rows IOExc eption, In validVista Credential sException , VistaMet hodExcepti on
  751           {
  752                    if(!  isConnect ed())
  753                             throw  new VistaI OException ("Vista co nnection h as not bee n establis hed yet, c all connec t() before  calling c all().");
  754                    
  755                    retu rn interna lCall(requ est);
  756           }* /
  757           
  758           pu blic synch ronized St ring call( VistaQuery  vistaQuer y)
  759           th rows IOExc eption, In validVista Credential sException , VistaMet hodExcepti on
  760           {
  761                    if(!  isConnect ed())
  762                             throw  new VistaI OException ("Vista co nnection h as not bee n establis hed yet, c all connec t() before  calling c all().");
  763                    
  764                    retu rn interna lCall(vist aQuery.bui ldMessage( getVistaCo nnectionTy pe()), get CallReadTi meout());
  765           }
  766           
  767           /* *
  768            *  An intern al (privat e) call th at allows  class meth ods to mak e
  769            *  calls bef ore the co nnection i s complete ly establi shed.
  770            *  
  771            *  @param re quest
  772            *  @return
  773            *  @throws I OException
  774            *  @throws I nvalidVist aCredentia lsExceptio
  775            *  @throws V istaMethod Exception 
  776            *  @throws V istaExcept ion
  777            * /
  778           pr ivate Stri ng interna lCall(Stri ng request , long rea dWait)
  779           th rows IOExc eption, In validVista Credential sException , VistaMet hodExcepti on
  780           {
  781                    setF ailedCall( false); //  reset for  this call
  782                    send (request);
  783                    retu rn recv(re adWait);
  784           }
  785  
  786           /* *
  787            *  
  788            *  @param ms g
  789            *  @throws I OException
  790            * /
  791           pr ivate sync hronized v oid send(S tring msg)  
  792           th rows IOExc eption
  793           {
  794                    Writ er out = n ew OutputS treamWrite r( getOutp utStreamIn ternal(),  "ASCII" );
  795                    out. write(msg) ;
  796                    out. flush();
  797           }
  798  
  799           /* *
  800            *  
  801            *  @return
  802            *  @throws V istaExcept ion
  803            *  @throws I OException
  804            *  @throws V istaMethod Exception 
  805            * /
  806           pr ivate sync hronized S tring recv (long wait
  807           th rows IOExc eption, In validVista Credential sException , VistaMet hodExcepti on
  808           {
  809                    Inpu tStreamRea der in = n ew InputSt reamReader
  810                             new Bu fferedInpu tStream(ge tInputStre amInternal ()), 
  811                             "ASCII " );
  812                    //In putStreamR eader in =  new Vista InputStrea mReader( n ew Buffere dInputStre am(getInpu tStreamInt ernal()),  "ASCII", 6 0000L );
  813  
  814                    int  c = nonBlo ckingRead( in, wait);       // r ead #of ch ars in sec urity erro r message
  815                    if(  c != 0 )              // if the  number of  chars is n ot 0 then  there is a  security  error mess age
  816                    {
  817                             String Buffer sec urityMessa geBuffer =  new Strin gBuffer();
  818                             
  819                             while(  (c = nonB lockingRea d(in, wait )) != -1 & & c != 0x0 4 )     //  not end o f stream a nd not EOT  (end of t ransmissio n)
  820                                      security MessageBuf fer.append ((char) c) ;
  821                             
  822                             // Som etimes c i s the firs t char and  not # of  chars
  823                             if( se curityMess ageBuffer. length() ! = c && Str ingUtils.i sAlphaChar ((char) c)  )
  824                                      security MessageBuf fer = secu rityMessag eBuffer.in sert(0, c) ;
  825                             
  826                             setFai ledCall(tr ue);
  827                             throw  new Invali dVistaCred entialsExc eption( se curityMess ageBuffer. toString() .trim() );
  828                    }
  829                    
  830                    c =  nonBlockin gRead(in,  wait);  //  read # of  chars in  applicatio n error me ssage
  831                    if ( c != 0)               // if the  number of  chars is n ot 0 then  there is a n applicat ion error  message
  832                    {
  833                             String Buffer app licationEr rorMessage Buffer = n ew StringB uffer();
  834                             
  835                             while  ((c = nonB lockingRea d(in, wait )) != -1 & & c != 4)  // not end  of stream  and not E OT (end of  transmiss ion)
  836                                      applicat ionErrorMe ssageBuffe r.append(( char) c);
  837                             
  838                             // Som etimes c i s the firs t char and  not # of  chars
  839                             if (ap plicationE rrorMessag eBuffer.le ngth() !=  c && Strin gUtils.isA lphaChar(( char) c))
  840                                      applicat ionErrorMe ssageBuffe r = applic ationError MessageBuf fer.insert (0, c);
  841                             
  842                             setFai ledCall(tr ue);
  843                             throw  new VistaM ethodExcep tion( appl icationErr orMessageB uffer.toSt ring().tri m() );
  844                    }
  845                    // N ow finally  read the  message...
  846                    Stri ngBuffer a pplication MessageBuf fer = new  StringBuff er();
  847                    whil e ((c = no nBlockingR ead(in, wa it)) != -1  && c != 4 )          // not end  of stream  and not E OT (end of  transmiss ion)
  848                             applic ationMessa geBuffer.a ppend((cha r) c);
  849                    
  850                    Stri ng respons e = applic ationMessa geBuffer.t oString(). trim();
  851                    if ( response.i ndexOf("M   ERROR", 0 ) != -1)
  852                    {
  853                             setFai ledCall(tr ue);
  854                             throw  new VistaM Exception( response);
  855                    }
  856                    
  857                    retu rn respons e;
  858           }
  859           
  860           /* *
  861            *  Waits up  to wait mi lliseconds  for a cha racter.
  862            *  Throws an  IOExcepti on if no c har are av ailable.
  863            *  
  864            *  @param in Stream
  865            *  @param wa it
  866            *  @return
  867            *  @throws I OException
  868            * /
  869           pu blic int n onBlocking Read(Input StreamRead er inStrea m, long wa it) 
  870           th rows IOExc eption
  871           {
  872                    if(w ait > 0)
  873                    {
  874                             long p ollingInte rval = get PollingInt erval();
  875                             long c urrentPoll ingInterva l = 2L; //  start wit h a 2 seco nd polling  interval  in case th e read wil l be ready  soon
  876                             long s tartWait =  System.cu rrentTimeM illis();
  877                             long e ndWait = s tartWait +  (wait > 0  ? wait :  0l);               //  pre-calcu late this  to save pr ocessing o n each loo p
  878                             boolea n expired  = false;
  879                             while(  ! inStrea m.ready()  && !(expir ed = (Syst em.current TimeMillis () > endWa it)) )
  880                             {
  881                                      try
  882                                      {
  883                                               Thread.sle ep(current PollingInt erval);
  884                                      }
  885                                      catch (I nterrupted Exception  x)
  886                                      {
  887                                               x.printSta ckTrace();
  888                                               throw new  IOExceptio n("Interru pted waiti ng for inp ut in recv () method. ", x);
  889                                      }
  890  
  891                                      if(curre ntPollingI nterval <  pollingInt erval)
  892                                      {
  893                                               // if the  current po lling inte rval is le ss than th e polling  interval
  894                                               // double  the pollin g interval
  895                                               currentPol lingInterv al *= 2;
  896                                               if(current PollingInt erval > po llingInter val)
  897                                               {
  898                                                       //  ensure th e polling  interval i s not abov e the desi red pollin g interval
  899                                                       cu rrentPolli ngInterval  = polling Interval;
  900                                               }
  901                                      }
  902                             }
  903                             if(exp ired)
  904                                      throw ne w IOExcept ion("Timed  out waiti ng " + wai t + " mill iseconds." );
  905                    }
  906                    
  907                    retu rn inStrea m.read();  // read a  character
  908           }
  909           
  910           pu blic synch ronized vo id disconn ect() 
  911           {
  912                    Vist aConnectio n.disconne ctRequests .add(this) ;
  913           }
  914           
  915           /* *
  916            *  Method to  immediate ly disconn ect the co nnection,  not go int o the disc onnect poo l.
  917            *  This shou ld only be  used for  debugging  purposes a nd not for  productio n use.
  918            * /
  919           pu blic synch ronized vo id disconn ectImmedia tely()
  920           {
  921                    try
  922                    {
  923                             intern alDisconne ct();
  924                    }
  925                    catc h(Throwabl e t)
  926                    {
  927                             logger .error("Er ror discon necting im mediately,  " + t.get Message()) ;
  928                    }
  929           }
  930           
  931           pu blic synch ronized vo id errorDi sconnect()  
  932           th rows IOExc eption 
  933           {
  934                    // J MW 4/19/20 12 - Chris  and I bel ieve that  in all cas es the bro ker should  make the  BYE call t o VistA -  even in an  error con dition.
  935                    // I t shouldn' t hurt and  if there  are any ex ceptions i t won't ma tter becau se the soc ket is the n closed
  936                    inte rnalDiscon nect();
  937                    /*
  938                    if(t his.connec ted)
  939                    {
  940                             if(thi s.transact ionSocket  != null &&  transacti onSocket.i sConnected ())
  941                                      this.tra nsactionSo cket.close ();
  942                             
  943                             this.t ransaction Socket = n ull;
  944                             connec ted = fals e;
  945                    }*/
  946           }
  947           
  948           /* *
  949            *  
  950            *  @throws V istaExcept ion
  951            *  @throws I OException
  952            * /
  953           pr ivate sync hronized v oid intern alDisconne ct() 
  954           th rows IOExc eption 
  955           {
  956                    if(  this.conne cted )
  957                    {
  958                             if(! t his.notify ListenersB eforeClose () )
  959                             {
  960                                      logger.w arn("Vista Connection Listener h as returne d false fr om connect ionClosing () thereby  preservin g connecti on.");
  961                                      return;
  962                             }
  963                             
  964                             String  msg = get VistaConne ctionType( ).getPrefi x();
  965                             if(get VistaConne ctionType( ) == Vista Connection Type.newSt yle)
  966                             {
  967                                      msg += " 10" + coun tWidth + " 04" + (cha r)5 + "#BY E#" + (cha r)4;
  968                             }
  969                             else
  970                             {
  971                                      msg += V istaQuery. strPack(Vi staQuery.s trPack("#B YE#", 5),  5);
  972                             }                
  973                             try
  974                {
  975                         msg = inte rnalCall(m sg, getDis connectRea dTimeout() );
  976                } 
  977                             catch  (InvalidVi staCredent ialsExcept ion e)
  978                {
  979                                      // shoul d never oc cur, an ar tifact of  the call()  method
  980                                      throw ne w IOExcept ion(e);
  981                } 
  982                             catch  (VistaMeth odExceptio n e)
  983                {
  984                                      // turn  this into  an IOExcep tion to ma ke it look  like
  985                                      // it is  a URLConn ection def ined call,  like conn ect()
  986                                      throw ne w IOExcept ion(e);
  987                }
  988                             finall y
  989                             {
  990                                      try
  991                                      {
  992                                               // @todo m sg should  contain "B YE" - do a nything if  it doesn' t?
  993                                               if(this.tr ansactionS ocket != n ull && tra nsactionSo cket.isCon nected())
  994                                                       th is.transac tionSocket .close();
  995                                              
  996                                               this.trans actionSock et = null;
  997                                               connected  = false;
  998                                      }
  999                                      catch(Ex ception ex )
  1000                                      {
  1001                                               // just in  case...
  1002                                               logger.war n("Excepti on closing  socket, "  + ex.getM essage());
  1003                                      }
  1004                             }
  1005                    }
  1006                    
  1007                    this .notifyLis tenersAfte rClose();
  1008           }
  1009  
  1010           
  1011           
  1012           /* *
  1013            *  Returns a n input st ream that  reads from  this open  connectio n.
  1014            *  
  1015            *  A SocketT imeoutExce ption can  be thrown  when readi ng from th e returned
  1016            *  input str eam if the  read time out expire s before d ata is ava ilable for
  1017            *  read.
  1018            *  
  1019            *  @return a n input st ream that  reads from  this open  connectio n.
  1020            *  @exceptio n IOExcept ion
  1021            *                  if a n I/O erro r occurs w hile creat ing the in put stream .
  1022            *  @exceptio n UnknownS erviceExce ption
  1023            *                  if t he protoco l does not  support i nput.
  1024            *  @see #set ReadTimeou t(int)
  1025            *  @see #get ReadTimeou t()
  1026            * /
  1027           @O verride
  1028           pu blic Input Stream get InputStrea m() 
  1029           th rows IOExc eption
  1030           {
  1031                    thro w new IOEx ception("V istaConnec tion does  not supppo rt direct  access to  streams, u se call()  method.");
  1032           }
  1033           
  1034           pr ivate Inpu tStream ge tInputStre amInternal () 
  1035           th rows IOExc eption
  1036           {
  1037                    retu rn this.tr ansactionS ocket == n ull ? null  : this.tr ansactionS ocket.getI nputStream ();
  1038           }
  1039  
  1040           /* *
  1041            *  Returns a n output s tream that  writes to  this conn ection.
  1042            *  
  1043            *  @return a n output s tream that  writes to  this conn ection.
  1044            *  @exceptio n IOExcept ion
  1045            *                  if a n I/O erro r occurs w hile creat ing the ou tput strea m.
  1046            *  @exceptio n UnknownS erviceExce ption
  1047            *                  if t he protoco l does not  support o utput.
  1048            * /
  1049           @O verride
  1050           pu blic Outpu tStream ge tOutputStr eam() 
  1051           th rows IOExc eption
  1052           {
  1053                    thro w new IOEx ception("V istaConnec tion does  not supppo rt direct  access to  streams, u se call()  method.");
  1054           }
  1055           
  1056           pr ivate Outp utStream g etOutputSt reamIntern al() 
  1057           th rows IOExc eption
  1058           {
  1059                    retu rn transac tionSocket  == null ?  null : tr ansactionS ocket.getO utputStrea m();
  1060           }
  1061  
  1062           //  ========= ========== ========== ========== ========== ========== ========== ========== ==
  1063           //  VistaConn ectionList ener Manag ement
  1064           //  ========= ========== ========== ========== ========== ========== ========== ========== ==
  1065           pr ivate Set< VistaConne ctionListe ner> liste ners = new  HashSet<V istaConnec tionListen er>();
  1066           
  1067           pu blic void  registerLi stener(Vis taConnecti onListener  listener)
  1068           {
  1069                    list eners.add( listener);
  1070           }
  1071           
  1072           pu blic void  unregister Listener(V istaConnec tionListen er listene r)
  1073           {
  1074                    list eners.remo ve(listene r);
  1075           }
  1076           
  1077           pr ivate bool ean notify ListenersB eforeOpen( )
  1078           {
  1079                    for( VistaConne ctionListe ner listen er : liste ners)
  1080                             if( !  listener.c onnectionO pening(thi s) )
  1081                                      return f alse;
  1082                    retu rn true;
  1083           }
  1084           
  1085           pr ivate void  notifyLis tenersAfte rOpen()
  1086           {
  1087                    for( VistaConne ctionListe ner listen er : liste ners)
  1088                             listen er.connect ionOpened( this);
  1089           }
  1090           
  1091           pr ivate bool ean notify ListenersB eforeClose ()
  1092           {
  1093                    for( VistaConne ctionListe ner listen er : liste ners)
  1094                             if( !  listener.c onnectionC losing(thi s) )
  1095                                      return f alse;
  1096                    retu rn true;
  1097           }
  1098           
  1099           pr ivate void  notifyLis tenersAfte rClose()
  1100           {
  1101                    for( VistaConne ctionListe ner listen er : liste ners)
  1102                             listen er.connect ionClosed( this);
  1103           }
  1104           
  1105           pr ivate Vist aConnectio nConfigura tion getVi staConnect ionConfigu ration()
  1106           {
  1107                    retu rn VistaCo nnectionCo nfiguratio n.getVista Connection Configurat ion();
  1108           }
  1109  
  1110           /* *
  1111            *  Returns t rue if the  most rece nt RPC cal l threw an  exception
  1112            *  
  1113            *  @return t he failedC all
  1114            * /
  1115           pu blic boole an isFaile dCall()
  1116           {
  1117                    retu rn failedC all;
  1118           }
  1119  
  1120           /* *
  1121            *  @param fa iledCall t he failedC all to set
  1122            * /
  1123           pr ivate void  setFailed Call(boole an failedC all)
  1124           {
  1125                    this .failedCal l = failed Call;
  1126           }
  1127   }