Produced by Araxis Merge on 12/5/2017 12:06:49 PM Central Standard 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.
| # | Location | File | Last Modified |
|---|---|---|---|
| 1 | IV-eHMP_CIF.zip\IMAG_Source\VISA\Java\VistaConnection\main\src\java\gov\va\med\imaging\url\vista | VistaConnection.java | Mon Dec 4 21:35:00 2017 UTC |
| 2 | IV-eHMP_CIF.zip\IMAG_Source\VISA\Java\VistaConnection\main\src\java\gov\va\med\imaging\url\vista | VistaConnection.java | Tue Dec 5 15:34:16 2017 UTC |
| Description | Between Files 1 and 2 |
|
|---|---|---|
| Text Blocks | Lines | |
| Unchanged | 3 | 2250 |
| Changed | 2 | 4 |
| Inserted | 0 | 0 |
| Removed | 0 | 0 |
| 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 |
No regular expressions were active.
| 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
|
|
| 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 n | |
| 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 n | |
| 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 | } |
Araxis Merge (but not the data content of this report) is Copyright © 1993-2016 Araxis Ltd (www.araxis.com). All rights reserved.