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.
# | 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 |
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 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 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.