Produced by Araxis Merge on 12/5/2017 12:06:38 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\CoreRouter\main\src\java\gov\va\med\server | CoreRouterFactory.java | Mon Dec 4 21:34:30 2017 UTC |
| 2 | IV-eHMP_CIF.zip\IMAG_Source\VISA\Java\CoreRouter\main\src\java\gov\va\med\server | CoreRouterFactory.java | Mon Dec 4 21:58:37 2017 UTC |
| Description | Between Files 1 and 2 |
|
|---|---|---|
| Text Blocks | Lines | |
| Unchanged | 2 | 770 |
| Changed | 1 | 2 |
| 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 | package go v.va.med.s erver; | |
| 2 | ||
| 3 | import gov .va.med.im aging.Imag ingMBean; | |
| 4 | //import g ov.va.med. imaging.co re.interfa ces.router .CommandFa ctory; | |
| 5 | import gov .va.med.im aging.core .interface s.router.R outerStati sticsAdvic e; | |
| 6 | import gov .va.med.se rver.Serve rLifecycle Event.Even tType; | |
| 7 | ||
| 8 | import jav a.lang.man agement.Ma nagementFa ctory; | |
| 9 | //import j ava.lang.r eflect.Con structor; | |
| 10 | //import j ava.lang.r eflect.Pro xy; | |
| 11 | //import j ava.util.A rrayList; | |
| 12 | import jav a.util.Enu meration; | |
| 13 | import jav a.util.Has htable; | |
| 14 | //import j ava.util.L ist; | |
| 15 | ||
| 16 | import jav ax.managem ent.Dynami cMBean; | |
| 17 | import jav ax.managem ent.MBeanE xception; | |
| 18 | import jav ax.managem ent.MBeanS erver; | |
| 19 | import jav ax.managem ent.Object Name; | |
| 20 | import jav ax.naming. Context; | |
| 21 | import jav ax.naming. Name; | |
| 22 | import jav ax.naming. RefAddr; | |
| 23 | import jav ax.naming. Reference; | |
| 24 | import jav ax.naming. spi.Object Factory; | |
| 25 | ||
| 26 | import org .apache.lo gging.log4 j.LogManag er; | |
| 27 | import org .apache.lo gging.log4 j.Logger; | |
| 28 | import org .springfra mework.bea ns.BeansEx ception; | |
| 29 | import org .springfra mework.con text.Appli cationCont ext; | |
| 30 | import org .springfra mework.con text.suppo rt.ClassPa thXmlAppli cationCont ext; | |
| 31 | ||
| 32 | /** | |
| 33 | * This cl ass implem ents the J NDI SPI Ob jectFactor y interfac e, providi ng | |
| 34 | * a way t o create R outer and AppConfigu ration ins tances and make them | |
| 35 | * availab le as Reso urces. | |
| 36 | * The app server ma y create m any copies of the cl ass, howev er only on e instance | |
| 37 | * of the applicatio n context (and conse quently th e router a nd app con figuration ) | |
| 38 | * should be created . To acco mplish thi s, the app lication c ontext ref erence (Sp ring) | |
| 39 | * is a st atic. Ref erences to the beans managed b y Spring ( Router and App Confi guration) | |
| 40 | * are man aged by th e Spring c ontext as singletons . The res ult is tha t the crea tion | |
| 41 | * of Rout er and App Configura tion as Si ngleton or Prototype is define d in the S pring cont ext. | |
| 42 | * | |
| 43 | * @author
|
|
| 44 | * | |
| 45 | */ | |
| 46 | public cla ss CoreRou terFactory | |
| 47 | implements ObjectFac tory | |
| 48 | { | |
| 49 | pu blic stati c final St ring LIFEC YCLE_ADAPT ER_BEAN_NA ME = "serv erLifecycl eAdapter"; | |
| 50 | pu blic stati c final St ring CORE_ ROUTER_BEA N_NAME = " router"; | |
| 51 | pu blic stati c final St ring COMMA ND_FACTORY _BEAN_NAME = "comman dFactory"; | |
| 52 | pu blic stati c final St ring ROUTE R_STATISTI CS_BEAN_NA ME = "rout erStatisti csAdvice"; | |
| 53 | pu blic stati c final St ring APPLI CATION_CON FIGURATION _BEAN_NAME = "appCon figuration "; | |
| 54 | pu blic stati c final St ring[] CON TEXT_FILEN AMES = new String[]{ "coreConte xt.xml"}; | |
| 55 | ||
| 56 | pr ivate stat ic final L ogger logg er = LogMa nager.getL ogger(Core RouterFact ory.class) ; | |
| 57 | pr ivate stat ic Applica tionContex t coreAppl icationCon text = nul l; | |
| 58 | ||
| 59 | pu blic CoreR outerFacto ry() | |
| 60 | { | |
| 61 | //Sy stem.out.p rintln("Ca cheFactory ctor BEGI N STACK TR ACE"); | |
| 62 | //Th read.dumpS tack(); | |
| 63 | //Sy stem.out.p rintln("Ca cheFactory ctor END STACK TRAC E"); | |
| 64 | //Sy stem.out.p rintln("Ca cheFactory ctor"); | |
| 65 | } | |
| 66 | ||
| 67 | /* * | |
| 68 | * If we are running i n an app s erver (whi ch is the only reaso n we'd be using this class) | |
| 69 | * then we M UST get ca che manage r referenc es through this meth od so that the manag er | |
| 70 | * will prop erly get t he app ser ver lifecy cle messag es. | |
| 71 | * | |
| 72 | * @return | |
| 73 | * @throws M BeanExcept ion | |
| 74 | * @throws C acheExcept ion | |
| 75 | * / | |
| 76 | pr ivate sync hronized s tatic Appl icationCon text getAp plicationC ontext() | |
| 77 | { | |
| 78 | if(c oreApplica tionContex t == null) | |
| 79 | { | |
| 80 | logger .info("Cre ating core VIX conte xt."); | |
| 81 | coreAp plicationC ontext = n ew ClassPa thXmlAppli cationCont ext( CONTE XT_FILENAM ES ); | |
| 82 | logger .info("Cor e VIX cont ext " + co reApplicat ionContext .hashCode( ) + " crea ted."); | |
| 83 | ||
| 84 | // get a referen ce to the server spe cific life cycle list ener as a server-agn ostic | |
| 85 | // ref erence and then regi ster ourse lves as in terested i n lifecycl e events | |
| 86 | // NOT E: there i s a bit of strangene ss with wh at is a st atic refer ence | |
| 87 | // ver sus the in stance ref erences. This arise s from the fact that Tomcat is creating | |
| 88 | // mul tiple inst ances of t his factor y but we w ant one re al instanc e to manag e | |
| 89 | // cre ation corr ectly. | |
| 90 | try | |
| 91 | { | |
| 92 | // registe r ourselve s as a ser ver lifecy cle listen er | |
| 93 | // we'll g et message s when the server is starting up or shut ting | |
| 94 | // down | |
| 95 | ServerAd apterImpl. getSinglet on().addSe rverLifecy cleListene r( | |
| 96 | ne w ServerLi fecycleLis tener() | |
| 97 | { | |
| 98 | @O verride | |
| 99 | pu blic void serverLife cycleEvent (ServerLif ecycleEven t event) | |
| 100 | { | |
| 101 | // t his instan ce delegat es to the static ser verLifecyc leEvent | |
| 102 | // m ethod | |
| 103 | Core RouterFact ory.server LifecycleE vent(event ); | |
| 104 | } | |
| 105 | } | |
| 106 | ); | |
| 107 | ||
| 108 | //register ResourceMB eans(); | |
| 109 | } | |
| 110 | catch (BeansExce ption bX) | |
| 111 | { | |
| 112 | StringBu ffer sb = new String Buffer(); | |
| 113 | sb.appen d("Unable to obtain a referenc e to the b ean named '"); | |
| 114 | sb.appen d(LIFECYCL E_ADAPTER_ BEAN_NAME) ; | |
| 115 | sb.appen d("', chec k the cont ext files: ("); | |
| 116 | for(Stri ng context Filename : CONTEXT_F ILENAMES) | |
| 117 | sb.append( contextFil ename + " "); | |
| 118 | sb.appen d(")."); | |
| 119 | ||
| 120 | LogManag er.getLogg er(CoreRou terFactory .class).er ror(sb.toS tring()); | |
| 121 | throw bX ; | |
| 122 | } | |
| 123 | } | |
| 124 | ||
| 125 | retu rn coreApp licationCo ntext; | |
| 126 | } | |
| 127 | ||
| 128 | /* * | |
| 129 | * Receives notificati on of serv er lifecyc le events (START and STOP) | |
| 130 | * @see gov. va.med.ser ver.Server LifecycleL istener#se rverLifecy cleEvent(g ov.va.med. server.Ser verLifecyc leEvent) | |
| 131 | * / | |
| 132 | privat e static v oid server LifecycleE vent(Serve rLifecycle Event even t) | |
| 133 | { | |
| 134 | if ( event.ge tEventType () == Even tType.STAR T ) | |
| 135 | logg er.info("S erverLifec ycleEvent START even t received by CoreRo uterFactor y."); | |
| 136 | el se if( eve nt.getEven tType() == EventType .STOP ) | |
| 137 | logg er.info("S erverLifec ycleEvent STOP event received by CoreRou terFactory ."); | |
| 138 | } | |
| 139 | ||
| 140 | ||
| 141 | /* * | |
| 142 | * | |
| 143 | * @return | |
| 144 | * @throws M BeanExcept ion | |
| 145 | * / | |
| 146 | pr ivate stat ic synchro nized gov. va.med.ima ging.core. interfaces .Router ge tRouter() | |
| 147 | { | |
| 148 | Appl icationCon text appCo ntext = ge tApplicati onContext( ); | |
| 149 | ||
| 150 | Stri ng msg = " CoreRouter Factory " + | |
| 151 | (appCo ntext == n ull ? "fai led to obt ain" : "ob tained") + | |
| 152 | " refe rence to a pplication context w hen gettin g router"; | |
| 153 | logg er.info(ms g); | |
| 154 | ||
| 155 | gov. va.med.ima ging.core. interfaces .Router ro uter = | |
| 156 | (gov.v a.med.imag ing.core.i nterfaces. Router)app Context.ge tBean(CORE _ROUTER_BE AN_NAME); | |
| 157 | ||
| 158 | msg = "CoreRou terFactory " + | |
| 159 | (route r == null ? "failed to obtain" : "obtain ed") + | |
| 160 | " refe rence to r outer from applicati on context ." + | |
| 161 | "Route r implemen tation is of type '" + (router == null ? "<null>" : router.g etClass(). getName()) + "'."; | |
| 162 | logg er.info(ms g); | |
| 163 | ||
| 164 | gov. va.med.ima ging.core. interfaces .router.Ro uterStatis ticsAdvice routerSta tistics = | |
| 165 | (gov.v a.med.imag ing.core.i nterfaces. router.Rou terStatist icsAdvice) appContext .getBean(R OUTER_STAT ISTICS_BEA N_NAME); | |
| 166 | regi sterRouter Statistics MBean(rout erStatisti cs); | |
| 167 | ||
| 168 | retu rn router; | |
| 169 | } | |
| 170 | ||
| 171 | /* * | |
| 172 | * @return | |
| 173 | * / | |
| 174 | pr ivate stat ic synchro nized gov. va.med.ima ging.core. interfaces .router.Co mmandFacto ry getComm andFactory () | |
| 175 | { | |
| 176 | Appl icationCon text appCo ntext = ge tApplicati onContext( ); | |
| 177 | ||
| 178 | Stri ng msg = " CoreRouter Factory " + | |
| 179 | (app Context == null ? "f ailed to o btain" : " obtained") + | |
| 180 | " re ference to applicati on context when gett ing comman d factory" ; | |
| 181 | logg er.info(ms g); | |
| 182 | ||
| 183 | gov. va.med.ima ging.core. interfaces .router.Co mmandFacto ry command Factory = | |
| 184 | (gov.v a.med.imag ing.core.i nterfaces. router.Com mandFactor y)appConte xt.getBean (COMMAND_F ACTORY_BEA N_NAME); | |
| 185 | ||
| 186 | msg = CoreRout erFactory. class.getS impleName( ) + | |
| 187 | (comma ndFactory == null ? | |
| 188 | " fail ed to obta in referen ce to comm and factor y from app lication c ontext" : | |
| 189 | " obta ined refer ence to Co mmandFacto ry of type [" + comm andFactory .getClass( ).getName( ) + "]" | |
| 190 | ); | |
| 191 | logg er.info(ms g); | |
| 192 | ||
| 193 | retu rn command Factory; | |
| 194 | } | |
| 195 | ||
| 196 | pr ivate stat ic ObjectN ame router Statistics MBeanName = null; | |
| 197 | /* * | |
| 198 | * This meth od should only be ca lled once, else MBea n exceptio ns will oc cur. | |
| 199 | * @param ro uterStatis tics | |
| 200 | * / | |
| 201 | pr ivate stat ic synchro nized void registerR outerStati sticsMBean (RouterSta tisticsAdv ice router Statistics ) | |
| 202 | { | |
| 203 | if(r outerStati sticsMBean Name != nu ll) | |
| 204 | return ; | |
| 205 | ||
| 206 | MBea nServer mB eanServer = Manageme ntFactory. getPlatfor mMBeanServ er(); | |
| 207 | ||
| 208 | if(r outerStati stics inst anceof Dyn amicMBean) | |
| 209 | { | |
| 210 | try | |
| 211 | { | |
| 212 | // Vista Imaging.Vi X:type=Cac he,name=Im agingExcha ngeCache | |
| 213 | Hashtabl e<String, String> mB eanPropert ies = new Hashtable< String, St ring>(); | |
| 214 | mBeanPro perties.pu t( "type", "RouterSt atistics" ); | |
| 215 | mBeanPro perties.pu t( "name", Integer.t oHexString (routerSta tistics.ha shCode()) ); | |
| 216 | routerSt atisticsMB eanName = new Object Name(Imagi ngMBean.VI X_MBEAN_DO MAIN_NAME, mBeanProp erties); | |
| 217 | mBeanServe r.register MBean(rout erStatisti cs, router Statistics MBeanName) ; | |
| 218 | } | |
| 219 | catch (Exception e){ LogMa nager.getL ogger(Core RouterFact ory.class) .error(e.t oString()) ; } | |
| 220 | } | |
| 221 | } | |
| 222 | ||
| 223 | /* * | |
| 224 | * | |
| 225 | * @return | |
| 226 | * / | |
| 227 | pr ivate stat ic synchro nized gov. va.med.ima ging.core. interfaces .IAppConfi guration g etApplicat ionConfigu ration() | |
| 228 | { | |
| 229 | Appl icationCon text appCo ntext = ge tApplicati onContext( ); | |
| 230 | ||
| 231 | Stri ng msg = C oreRouterF actory.cla ss.getSimp leName() + | |
| 232 | (appCo ntext == n ull ? " fa iled to ob tain" : " obtained") + | |
| 233 | " refe rence to a pplication context w hen gettin g applicat ion config uration."; | |
| 234 | logg er.info(ms g); | |
| 235 | ||
| 236 | ||
| 237 | gov. va.med.ima ging.core. interfaces .IAppConfi guration a pplication Configurat ion = | |
| 238 | (gov.v a.med.imag ing.core.i nterfaces. IAppConfig uration)ap pContext.g etBean(APP LICATION_C ONFIGURATI ON_BEAN_NA ME); | |
| 239 | ||
| 240 | msg = CoreRout erFactory. class.getS impleName( ) + | |
| 241 | (appli cationConf iguration == null ? " failed t o obtain" : " obtain ed") + | |
| 242 | " refe rence to a pplication configura tion from applicatio n context. "; | |
| 243 | logg er.info(ms g); | |
| 244 | ||
| 245 | retu rn applica tionConfig uration; | |
| 246 | } | |
| 247 | ||
| 248 | /* * | |
| 249 | * @pa ram obj Th e possibly null obje ct contain ing locati on or | |
| 250 | * re ference in formation that can b e used in creating a n object | |
| 251 | * @pa ram name T he name of this obje ct relativ e to <code >nameCtx</ code> | |
| 252 | * @pa ram nameCt x The cont ext relati ve to whic h the <cod e>name</co de> | |
| 253 | * pa rameter is specified , or <code >null</cod e> if <cod e>name</co de> | |
| 254 | * is relative to the def ault initi al context | |
| 255 | * @pa ram enviro nment The possibly n ull enviro nment that is used i n | |
| 256 | * cr eating thi s object | |
| 257 | * | |
| 258 | * Fo r the foll owing elem ent in ser ver.xml: | |
| 259 | * <Re source | |
| 260 | * aut h="Contain er" | |
| 261 | * des cription=" Core appli cation (Sp ring) cont ext" | |
| 262 | * nam e="CoreRou terContext " | |
| 263 | * typ e="org.spr ingframewo rk.context .Applicati onContext" | |
| 264 | * ins tance-name ="CoreRout erContext" | |
| 265 | * fac tory="gov. va.med.ser ver.tomcat .CoreRoute rContextFa ctory" | |
| 266 | * /> | |
| 267 | * | |
| 268 | * na meCts = 'o rg.apache. naming.Nam ingContext @787d6a' | |
| 269 | * na me.toStrin g = 'Imagi ngExchange Cache' | |
| 270 | * | |
| 271 | * Re ference fa ctory clas sname[org. apache.nam ing.factor y.Resource Factory], factory c lass locat ion [null] | |
| 272 | * Re fAddr type [descript ion] = [Ca ching mech anism for ViXS] | |
| 273 | * Re fAddr type [scope] = [Shareabl e] | |
| 274 | * Re fAddr type [auth] = [Container ] | |
| 275 | * Re fAddr type [factory] = [gov.va .med.imagi ng.storage .cache.imp l.tomcat.C acheFactor y] | |
| 276 | * | |
| 277 | * ja vax.naming .Name [.Im agingExcha ngeCache] | |
| 278 | * / | |
| 279 | pu blic Objec t getObjec tInstance( | |
| 280 | Object obj, | |
| 281 | Name n ame, | |
| 282 | Contex t nameCtx, | |
| 283 | Hashta ble<?, ?> environmen t | |
| 284 | ) | |
| 285 | th rows Excep tion | |
| 286 | { | |
| 287 | // We only k now how to deal with <code>jav ax.naming. Reference< /code>s | |
| 288 | // that spec ify a clas s name of "gov.va.me d.imaging. storage.ca che.Cache" | |
| 289 | if ( (obj == null) || ! (obj insta nceof Refe rence) ) | |
| 290 | return n ull; | |
| 291 | ||
| 292 | // The JNDI defines th e Referenc e class to represent reference . | |
| 293 | // A referen ce contain s informat ion on how to constr uct a copy of the ob ject. | |
| 294 | // The JNDI will attem pt to turn reference s looked u p from the directory into the Java objec ts that th ey | |
| 295 | // represent so that J NDI client s have the illusion that what is stored in the dir ectory are Java obje cts. | |
| 296 | Re ference re f = (Refer ence) obj; | |
| 297 | ||
| 298 | // Best gues s; the pro perties of the Refer ence insta nce come f rom the se rver.xml f ile, Resou rce elemen t: | |
| 299 | // <Resource | |
| 300 | // auth="Con tainer" | |
| 301 | // descripti on="Core a pplication (Spring) context" | |
| 302 | // name="Cor eRouterCon text" | |
| 303 | // type="org .springfra mework.con text.Appli cationCont ext" | |
| 304 | // instance- name="Core RouterCont ext" | |
| 305 | // factory=" gov.va.med .server.to mcat.CoreR outerConte xtFactory" /> | |
| 306 | ||
| 307 | lo gger.info( getClass() .getSimple Name() + " getObject Instance(R eference, '" + | |
| 308 | name.t oString() + "', '" + nameCtx.t oString() + ", ...) " ); | |
| 309 | lo gger.info( "begin Ref erence con tents ==== ========== ======== " ); | |
| 310 | lo gger.info( dumpRefere nceContent s(ref)); | |
| 311 | lo gger.info( "end Ref erence con tents ==== ========== ======== " ); | |
| 312 | ||
| 313 | // System.out .println(d umpName(na me)); | |
| 314 | Stri ng resourc eName = na me.toStrin g(); | |
| 315 | ||
| 316 | // t his refere nce will c ontain the reference that is b eing reque sted | |
| 317 | Ob ject imple mentation = null; | |
| 318 | ||
| 319 | St ring msg = getClass( ).getSimpl eName() + " getting reference to '" + re sourceName + "', exp ected type is [" + r ef.getClas sName() + "]."; | |
| 320 | lo gger.info( msg); | |
| 321 | ||
| 322 | // T he router implementa tion is de termined b y the Spri ng context | |
| 323 | if ( gov.va.m ed.imaging .core.inte rfaces.Rou ter.class. getName(). equals(ref .getClassN ame()) ) | |
| 324 | { | |
| 325 | impl ementation = getRout er(); | |
| 326 | } | |
| 327 | ||
| 328 | // The comma nd factory may be su bstituted by changin g the cont ext.xml (S pring cont ext) file. | |
| 329 | el se if(gov. va.med.ima ging.core. interfaces .router.Co mmandFacto ry.class.g etName().e quals(ref. getClassNa me())) | |
| 330 | { | |
| 331 | impl ementation = getComm andFactory (); | |
| 332 | } | |
| 333 | ||
| 334 | el se if( gov .va.med.im aging.core .interface s.IAppConf iguration. class.getN ame().equa ls(ref.get ClassName( )) ) | |
| 335 | { | |
| 336 | impl ementation = getAppl icationCon figuration (); | |
| 337 | } | |
| 338 | ||
| 339 | if (implement ation == n ull) | |
| 340 | { | |
| 341 | logg er.error( getClass() .getSimple Name() + " reference to '" + r esourceNam e + "' is null." ); | |
| 342 | } | |
| 343 | el se | |
| 344 | { | |
| 345 | msg = | |
| 346 | getCla ss().getSi mpleName() + " refer ence to '" + resourc eName + "' is " + | |
| 347 | (imple mentation == null ? "null" : " [" + imple mentation. getClass() .getName() + "]") + "."; | |
| 348 | ||
| 349 | logg er.info(ge tClass().g etSimpleNa me() + " r eference t o '" + res ourceName + "' is of type [" + implement ation.getC lass().get Name() + " ]." ); | |
| 350 | ||
| 351 | } | |
| 352 | ||
| 353 | re turn imple mentation; | |
| 354 | } | |
| 355 | ||
| 356 | pr ivate Obje ct dumpNam e(Name nam e) | |
| 357 | { | |
| 358 | Stri ngBuilder sb = new S tringBuild er(); | |
| 359 | ||
| 360 | sb.a ppend("jav ax.naming. Name ["); | |
| 361 | for( Enumerati on<String> enumName = name.get All(); enu mName.hasM oreElement s(); ) | |
| 362 | { | |
| 363 | sb.app end(sb.len gth() > 0 ? "." :"") ; | |
| 364 | sb.app end( enumN ame.nextEl ement() ); | |
| 365 | } | |
| 366 | sb.a ppend("]") ; | |
| 367 | retu rn sb.toSt ring(); | |
| 368 | } | |
| 369 | ||
| 370 | pu blic Strin g dumpRefe renceConte nts(Refere nce ref) | |
| 371 | { | |
| 372 | Stri ngBuilder sb = new S tringBuild er(); | |
| 373 | ||
| 374 | sb.a ppend("Ref erence cla ssname[" + ref.getCl assName() + "]\n"); | |
| 375 | sb.a ppend("Ref erence fac tory class name[" + r ef.getFact oryClassNa me() + | |
| 376 | "], fac tory class location [" + ref.g etFactoryC lassLocati on() + "]\ n"); | |
| 377 | ||
| 378 | for( Enumerati on<RefAddr > enumRefA ddr = ref. getAll(); enumRefAdd r.hasMoreE lements(); ) | |
| 379 | { | |
| 380 | RefAdd r refAddr = enumRefA ddr.nextEl ement(); | |
| 381 | sb.app end(" Ref Addr type [" + refAd dr.getType () + "] = [" + refAd dr.getCont ent().toSt ring() + " ]\n"); | |
| 382 | } | |
| 383 | ||
| 384 | retu rn sb.toSt ring(); | |
| 385 | } | |
| 386 | } |
Araxis Merge (but not the data content of this report) is Copyright © 1993-2016 Araxis Ltd (www.araxis.com). All rights reserved.