001 package railo.runtime.orm; 002 003 import java.io.IOException; 004 import java.util.ArrayList; 005 import java.util.Iterator; 006 007 import org.w3c.dom.Attr; 008 import org.w3c.dom.Element; 009 import org.w3c.dom.NamedNodeMap; 010 011 import railo.commons.digest.MD5; 012 import railo.commons.io.res.Resource; 013 import railo.commons.io.res.util.ResourceUtil; 014 import railo.commons.lang.StringUtil; 015 import railo.runtime.PageContext; 016 import railo.runtime.PageSource; 017 import railo.runtime.config.Config; 018 import railo.runtime.config.ConfigWebImpl; 019 import railo.runtime.engine.ThreadLocalPageContext; 020 import railo.runtime.exp.ExpressionException; 021 import railo.runtime.listener.ApplicationContext; 022 import railo.runtime.op.Caster; 023 import railo.runtime.op.Decision; 024 import railo.runtime.type.Array; 025 import railo.runtime.type.ArrayImpl; 026 import railo.runtime.type.Collection; 027 import railo.runtime.type.KeyImpl; 028 import railo.runtime.type.Struct; 029 import railo.runtime.type.StructImpl; 030 import railo.runtime.type.util.KeyConstants; 031 import railo.runtime.type.util.ListUtil; 032 033 public class ORMConfigurationImpl implements ORMConfiguration { 034 public static final int DBCREATE_NONE=0; 035 public static final int DBCREATE_UPDATE=1; 036 public static final int DBCREATE_DROP_CREATE=2; 037 038 public static final Collection.Key AUTO_GEN_MAP = KeyImpl.intern("autogenmap"); 039 public static final Collection.Key CATALOG = KeyImpl.intern("catalog"); 040 public static final Collection.Key IS_DEFAULT_CFC_LOCATION = KeyImpl.intern("isDefaultCfclocation"); 041 public static final Collection.Key DB_CREATE = KeyImpl.intern("dbCreate"); 042 public static final Collection.Key DIALECT = KeyImpl.intern("dialect"); 043 public static final Collection.Key FLUSH_AT_REQUEST_END = KeyImpl.intern("flushAtRequestEnd"); 044 public static final Collection.Key LOG_SQL = KeyImpl.intern("logSql"); 045 public static final Collection.Key SAVE_MAPPING = KeyImpl.intern("savemapping"); 046 public static final Collection.Key SCHEMA = KeyImpl.intern("schema"); 047 public static final Collection.Key SECONDARY_CACHE_ENABLED = KeyImpl.intern("secondarycacheenabled"); 048 public static final Collection.Key SQL_SCRIPT = KeyImpl.intern("sqlscript"); 049 public static final Collection.Key USE_DB_FOR_MAPPING = KeyImpl.intern("useDBForMapping"); 050 public static final Collection.Key CACHE_CONFIG = KeyImpl.intern("cacheconfig"); 051 public static final Collection.Key CACHE_PROVIDER = KeyImpl.intern("cacheProvider"); 052 public static final Collection.Key ORM_CONFIG = KeyImpl.intern("ormConfig"); 053 public static final Collection.Key EVENT_HANDLING = KeyImpl.intern("eventHandling"); 054 public static final Collection.Key EVENT_HANDLER = KeyImpl.intern("eventHandler"); 055 public static final Collection.Key AUTO_MANAGE_SESSION = KeyImpl.intern("autoManageSession"); 056 public static final Collection.Key NAMING_STRATEGY = KeyImpl.intern("namingstrategy"); 057 058 059 private boolean autogenmap=true; 060 private String catalog; 061 private Resource[] cfcLocations; 062 private int dbCreate=DBCREATE_NONE; 063 private String dialect; 064 private Boolean eventHandling=null; 065 private boolean flushAtRequestEnd=true; 066 private boolean logSQL; 067 private boolean saveMapping; 068 private String schema; 069 private boolean secondaryCacheEnabled; 070 private Resource sqlScript; 071 private boolean useDBForMapping=true; 072 private Resource cacheConfig; 073 private String cacheProvider; 074 private Resource ormConfig; 075 private String eventHandler; 076 private String namingStrategy; 077 private boolean isDefaultCfcLocation=true; 078 private boolean skipCFCWithError=true; 079 private boolean autoManageSession=true; 080 081 private ORMConfigurationImpl(){ 082 autogenmap=true; 083 dbCreate=DBCREATE_NONE; 084 flushAtRequestEnd=true; 085 useDBForMapping=true; 086 } 087 088 089 090 091 092 093 public static ORMConfiguration load(Config config,ApplicationContext ac, Element el, Resource defaultCFCLocation,ORMConfiguration defaultConfig) { 094 return _load(config,ac, new _GetElement(el),defaultCFCLocation,defaultConfig); 095 } 096 097 public static ORMConfiguration load(Config config,ApplicationContext ac,Struct settings, Resource defaultCFCLocation,ORMConfiguration defaultConfig) { 098 return _load(config,ac, new _GetStruct(settings),defaultCFCLocation,defaultConfig); 099 } 100 101 private static ORMConfiguration _load(Config config,ApplicationContext ac, _Get settings, Resource defaultCFCLocation,ORMConfiguration dc) { 102 103 if(dc==null)dc=new ORMConfigurationImpl(); 104 ORMConfigurationImpl c = ((ORMConfigurationImpl)dc).duplicate(); 105 c.cfcLocations=defaultCFCLocation==null?new Resource[0]:new Resource[]{defaultCFCLocation}; 106 107 // autogenmap 108 c.autogenmap=Caster.toBooleanValue(settings.get(AUTO_GEN_MAP,dc.autogenmap()),dc.autogenmap()); 109 110 // catalog 111 c.catalog=StringUtil.trim(Caster.toString(settings.get(CATALOG,dc.getCatalog()),dc.getCatalog()),dc.getCatalog()); 112 113 // cfclocation 114 Object obj = settings.get(KeyConstants._cfcLocation,null); 115 116 if(obj!=null){ 117 java.util.List<Resource> list=loadCFCLocation(config,ac,obj,true); 118 119 if(list!=null && list.size()>0){ 120 c.cfcLocations=list.toArray(new Resource[list.size()]); 121 c.isDefaultCfcLocation=false; 122 } 123 } 124 if(c.cfcLocations == null) 125 c.cfcLocations=defaultCFCLocation==null?new Resource[0]:new Resource[]{defaultCFCLocation}; 126 127 // dbcreate 128 obj = settings.get(DB_CREATE,null); 129 if(obj!=null){ 130 String str = Caster.toString(obj,"").trim().toLowerCase(); 131 c.dbCreate=dbCreateAsInt(str); 132 } 133 134 // dialect 135 c.dialect = StringUtil.trim(Caster.toString(settings.get(DIALECT,dc.getDialect()),dc.getDialect()),dc.getDialect()); 136 137 // namingstrategy 138 c.namingStrategy=Caster.toString(settings.get(NAMING_STRATEGY,dc.namingStrategy()),dc.namingStrategy()); 139 140 // eventHandler 141 c.eventHandler=Caster.toString(settings.get(EVENT_HANDLER,dc.eventHandler()),dc.eventHandler()); 142 143 // eventHandling 144 Boolean b=Caster.toBoolean(settings.get(EVENT_HANDLING,null),null); 145 if(b==null) { 146 if(dc.eventHandling()) 147 b=Boolean.TRUE; 148 else 149 b=!StringUtil.isEmpty(c.eventHandler,true); 150 } 151 c.eventHandling=b; 152 153 // flushatrequestend 154 c.flushAtRequestEnd=Caster.toBooleanValue(settings.get(FLUSH_AT_REQUEST_END,dc.flushAtRequestEnd()),dc.flushAtRequestEnd()); 155 156 // logSQL 157 c.logSQL=Caster.toBooleanValue(settings.get(LOG_SQL,dc.logSQL()),dc.logSQL()); 158 159 160 // autoManageSession 161 c.autoManageSession=Caster.toBooleanValue(settings.get(AUTO_MANAGE_SESSION,dc.autoManageSession()),dc.autoManageSession()); 162 163 // skipCFCWithError 164 c.skipCFCWithError=Caster.toBooleanValue(settings.get(KeyConstants._skipCFCWithError,dc.skipCFCWithError()),dc.skipCFCWithError()); 165 166 // savemapping 167 c.saveMapping=Caster.toBooleanValue(settings.get(SAVE_MAPPING,dc.saveMapping()),dc.saveMapping()); 168 169 // schema 170 c.schema=StringUtil.trim(Caster.toString(settings.get(SCHEMA,dc.getSchema()),dc.getSchema()),dc.getSchema()); 171 172 // secondarycacheenabled 173 c.secondaryCacheEnabled=Caster.toBooleanValue(settings.get(SECONDARY_CACHE_ENABLED,dc.secondaryCacheEnabled()),dc.secondaryCacheEnabled()); 174 175 // sqlscript 176 obj = settings.get(SQL_SCRIPT,null); 177 if(!StringUtil.isEmpty(obj)){ 178 try { 179 c.sqlScript=toRes(config, obj, true); 180 } catch (ExpressionException e) { 181 //print.e(e); 182 } 183 } 184 185 // useDBForMapping 186 c.useDBForMapping=Caster.toBooleanValue(settings.get(USE_DB_FOR_MAPPING,dc.useDBForMapping()),dc.useDBForMapping()); 187 188 // cacheconfig 189 obj = settings.get(CACHE_CONFIG,null); 190 if(!StringUtil.isEmpty(obj)){ 191 try { 192 c.cacheConfig=toRes(config, obj, true); 193 } catch (ExpressionException e) { 194 //print.printST(e); 195 } 196 } 197 198 // cacheprovider 199 c.cacheProvider=StringUtil.trim(Caster.toString(settings.get(CACHE_PROVIDER,dc.getCacheProvider()),dc.getCacheProvider()),dc.getCacheProvider()); 200 201 // ormconfig 202 obj = settings.get(ORM_CONFIG,null); 203 if(!StringUtil.isEmpty(obj)){ 204 try { 205 c.ormConfig=toRes(config, obj, true); 206 } catch (ExpressionException e) { 207 //print.printST(e); 208 } 209 } 210 211 return c; 212 } 213 214 public static java.util.List<Resource> loadCFCLocation(Config config, ApplicationContext ac,Object obj, boolean onlyDir) { 215 216 Resource res; 217 if(!Decision.isArray(obj)){ 218 String list = Caster.toString(obj,null); 219 if(!StringUtil.isEmpty(list)) { 220 obj=ListUtil.listToArray(list, ','); 221 } 222 } 223 224 if(Decision.isArray(obj)) { 225 Array arr=Caster.toArray(obj,null); 226 java.util.List<Resource> list=new ArrayList<Resource>(); 227 Iterator<Object> it = arr.valueIterator(); 228 while(it.hasNext()){ 229 try { 230 res=toResourceExisting(config,ac,it.next(),onlyDir); 231 if(res!=null) list.add(res); 232 } 233 catch(Throwable t){} 234 } 235 return list; 236 } 237 238 239 return null; 240 } 241 242 243 244 245 246 247 private static Resource toRes(Config config, Object obj, boolean existing) throws ExpressionException { 248 PageContext pc = ThreadLocalPageContext.get(); 249 if(pc!=null)return Caster.toResource(pc, obj, existing); 250 return Caster.toResource(config, obj, existing); 251 } 252 253 private static Resource toResourceExisting(Config config, ApplicationContext ac,Object obj, boolean onlyDir) { 254 //Resource root = config.getRootDirectory(); 255 String path = Caster.toString(obj,null); 256 if(StringUtil.isEmpty(path,true)) return null; 257 path=path.trim(); 258 Resource res; 259 PageContext pc = ThreadLocalPageContext.get(); 260 261 // first check relative to application.cfc 262 if(pc!=null) { 263 if(ac==null) ac= pc.getApplicationContext(); 264 265 // abs path 266 if(path.startsWith("/")){ 267 ConfigWebImpl cwi=(ConfigWebImpl) config; 268 PageSource ps = cwi.getPageSourceExisting( 269 pc, ac==null?null:ac.getMappings(), path, false, false, true, false); 270 //res=cwi.getPhysicalResourceExistingX( 271 // pc, 272 // ac==null?null:ac.getMappings(), path, 273 // false, false, true); 274 if(ps!=null){ 275 res=ps.getResource(); 276 if(res!=null && (!onlyDir || res.isDirectory())) return res; 277 } 278 279 } 280 // real path 281 else { 282 Resource src= ac!=null?ac.getSource():null; 283 if(src!=null) { 284 res=src.getParentResource().getRealResource(path); 285 if(res!=null && (!onlyDir || res.isDirectory())) return res; 286 } 287 // happens when this is called from within the application.cfc (init) 288 else { 289 res=ResourceUtil.toResourceNotExisting(pc, path); 290 if(res!=null && (!onlyDir || res.isDirectory())) return res; 291 } 292 } 293 } 294 295 296 297 // then in the webroot 298 res=config.getRootDirectory().getRealResource(path); 299 if(res!=null && (!onlyDir || res.isDirectory())) return res; 300 301 // then absolute 302 res = ResourceUtil.toResourceNotExisting(config, path); 303 304 if(res!=null && (!onlyDir || res.isDirectory())) return res; 305 return null; 306 } 307 308 309 310 311 312 313 private ORMConfigurationImpl duplicate() { 314 315 ORMConfigurationImpl other = new ORMConfigurationImpl(); 316 317 318 319 other.autogenmap=autogenmap; 320 other.catalog=catalog; 321 other.cfcLocations=cfcLocations; 322 other.isDefaultCfcLocation=isDefaultCfcLocation; 323 other.dbCreate=dbCreate; 324 other.dialect=dialect; 325 other.eventHandler=eventHandler; 326 other.namingStrategy=namingStrategy; 327 other.eventHandling=eventHandling; 328 other.flushAtRequestEnd=flushAtRequestEnd; 329 other.logSQL=logSQL; 330 other.saveMapping=saveMapping; 331 other.schema=schema; 332 other.secondaryCacheEnabled=secondaryCacheEnabled; 333 other.sqlScript=sqlScript; 334 other.useDBForMapping=useDBForMapping; 335 other.cacheConfig=cacheConfig; 336 other.cacheProvider=cacheProvider; 337 other.ormConfig=ormConfig; 338 other.autoManageSession=autoManageSession; 339 other.skipCFCWithError=skipCFCWithError; 340 return other; 341 } 342 343 public String hash() { 344 345 String data=autogenmap+":"+catalog+":"+isDefaultCfcLocation 346 +":"+dbCreate+":"+dialect+":"+eventHandling+":"+namingStrategy+":"+eventHandler+":"+flushAtRequestEnd+":"+logSQL+":"+autoManageSession+":"+skipCFCWithError+":"+saveMapping+":"+schema+":"+secondaryCacheEnabled+":"+ 347 useDBForMapping+":"+cacheProvider 348 349 +":"+toStr(cfcLocations)+":"+toStr(sqlScript)+":"+toStr(cacheConfig)+":"+toStr(ormConfig) 350 ; 351 352 try { 353 return MD5.getDigestAsString(data); 354 } catch (IOException e) { 355 return null; 356 } 357 } 358 359 360 361 362 363 private String toStr(Resource res) { 364 if(res==null) return ""; 365 return res.getAbsolutePath(); 366 } 367 private String toStr(Resource[] reses) { 368 if(reses==null) return ""; 369 StringBuilder sb=new StringBuilder(); 370 for(int i=0;i<reses.length;i++){ 371 sb.append(toStr(reses[i])); 372 } 373 return sb.toString(); 374 } 375 376 377 378 379 380 381 /** 382 * @return the autogenmap 383 */ 384 public boolean autogenmap() { 385 return autogenmap; 386 } 387 388 /** 389 * @return the catalog 390 */ 391 public String getCatalog() { 392 return catalog; 393 } 394 395 /** 396 * @return the cfcLocation 397 */ 398 public Resource[] getCfcLocations() { 399 return cfcLocations; 400 } 401 public boolean isDefaultCfcLocation() { 402 return isDefaultCfcLocation; 403 } 404 405 /** 406 * @return the dbCreate 407 */ 408 public int getDbCreate() { 409 return dbCreate; 410 } 411 412 /** 413 * @return the dialect 414 */ 415 public String getDialect() { 416 return dialect; 417 } 418 419 /** 420 * @return the eventHandling 421 */ 422 public boolean eventHandling() { 423 return eventHandling==null?false:eventHandling.booleanValue(); 424 } 425 426 public String eventHandler() { 427 return eventHandler; 428 } 429 430 public String namingStrategy() { 431 return namingStrategy; 432 } 433 434 435 436 /** 437 * @return the flushAtRequestEnd 438 */ 439 public boolean flushAtRequestEnd() { 440 return flushAtRequestEnd; 441 } 442 443 /** 444 * @return the logSQL 445 */ 446 public boolean logSQL() { 447 return logSQL; 448 } 449 450 /** 451 * @return the saveMapping 452 */ 453 public boolean saveMapping() { 454 return saveMapping; 455 } 456 457 /** 458 * @return the schema 459 */ 460 public String getSchema() { 461 return schema; 462 } 463 464 /** 465 * @return the secondaryCacheEnabled 466 */ 467 public boolean secondaryCacheEnabled() { 468 return secondaryCacheEnabled; 469 } 470 471 /** 472 * @return the sqlScript 473 */ 474 public Resource getSqlScript() { 475 return sqlScript; 476 } 477 478 /** 479 * @return the useDBForMapping 480 */ 481 public boolean useDBForMapping() { 482 return useDBForMapping; 483 } 484 485 /** 486 * @return the cacheConfig 487 */ 488 public Resource getCacheConfig() { 489 return cacheConfig; 490 } 491 492 /** 493 * @return the cacheProvider 494 */ 495 public String getCacheProvider() { 496 return cacheProvider; 497 } 498 499 /** 500 * @return the ormConfig 501 */ 502 public Resource getOrmConfig() { 503 return ormConfig; 504 } 505 506 public boolean skipCFCWithError() { 507 return skipCFCWithError; 508 } 509 public boolean autoManageSession() { 510 return autoManageSession; 511 } 512 513 514 515 516 public Object toStruct() { 517 518 Resource[] locs = getCfcLocations(); 519 Array arrLocs=new ArrayImpl(); 520 if(locs!=null)for(int i=0;i<locs.length;i++){ 521 arrLocs.appendEL(getAbsolutePath(locs[i])); 522 } 523 Struct sct=new StructImpl(); 524 sct.setEL(AUTO_GEN_MAP,this.autogenmap()); 525 sct.setEL(CATALOG,StringUtil.emptyIfNull(getCatalog())); 526 sct.setEL(KeyConstants._cfcLocation,arrLocs); 527 sct.setEL(IS_DEFAULT_CFC_LOCATION,isDefaultCfcLocation()); 528 sct.setEL(DB_CREATE,dbCreateAsString(getDbCreate())); 529 sct.setEL(DIALECT,StringUtil.emptyIfNull(getDialect())); 530 sct.setEL(EVENT_HANDLING,eventHandling()); 531 sct.setEL(EVENT_HANDLER,eventHandler()); 532 sct.setEL(NAMING_STRATEGY,namingStrategy()); 533 sct.setEL(FLUSH_AT_REQUEST_END,flushAtRequestEnd()); 534 sct.setEL(LOG_SQL,logSQL()); 535 sct.setEL(SAVE_MAPPING,saveMapping()); 536 sct.setEL(SCHEMA,StringUtil.emptyIfNull(getSchema())); 537 sct.setEL(SECONDARY_CACHE_ENABLED,secondaryCacheEnabled()); 538 sct.setEL(SQL_SCRIPT,StringUtil.toStringEmptyIfNull(getSqlScript())); 539 sct.setEL(USE_DB_FOR_MAPPING,useDBForMapping()); 540 sct.setEL(CACHE_CONFIG,getAbsolutePath(getCacheConfig())); 541 sct.setEL(CACHE_PROVIDER,StringUtil.emptyIfNull(getCacheProvider())); 542 sct.setEL(ORM_CONFIG,getAbsolutePath(getOrmConfig())); 543 544 545 return sct; 546 } 547 548 549 private static String getAbsolutePath(Resource res) { 550 if(res==null )return ""; 551 return res.getAbsolutePath(); 552 } 553 554 555 556 557 558 559 public static int dbCreateAsInt(String dbCreate) { 560 if(dbCreate==null)dbCreate=""; 561 else dbCreate=dbCreate.trim().toLowerCase(); 562 563 if("update".equals(dbCreate))return DBCREATE_UPDATE; 564 if("dropcreate".equals(dbCreate))return DBCREATE_DROP_CREATE; 565 if("drop-create".equals(dbCreate))return DBCREATE_DROP_CREATE; 566 567 return DBCREATE_NONE; 568 } 569 570 571 572 573 public static String dbCreateAsString(int dbCreate) { 574 575 switch(dbCreate){ 576 case DBCREATE_DROP_CREATE: return "dropcreate"; 577 case DBCREATE_UPDATE: return "update"; 578 } 579 580 return "none"; 581 } 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 } 599 600 interface _Get { 601 public Object get(Collection.Key name,Object defaultValue); 602 } 603 604 class _GetStruct implements _Get { 605 606 private Struct sct; 607 public _GetStruct(Struct sct){ 608 this.sct=sct; 609 } 610 611 public Object get(Collection.Key name,Object defaultValue){ 612 return sct.get(name,defaultValue); 613 } 614 615 public String toString(){ 616 return "_GetStruct:"+sct.toString(); 617 } 618 } 619 620 class _GetElement implements _Get { 621 622 private Element el; 623 public _GetElement(Element el){ 624 this.el=el; 625 } 626 public Object get(Collection.Key name,Object defaultValue){ 627 String value=_get(name.getString()); 628 if(value==null)value = _get(StringUtil.camelToHypenNotation(name.getString())); 629 if(value==null)value = _get(name.getLowerString()); 630 if(value==null){ 631 NamedNodeMap map = el.getAttributes(); 632 int len=map.getLength(); 633 Attr attr; 634 String n; 635 for(int i=0;i<len;i++){ 636 attr=(Attr) map.item(i); 637 n=attr.getName(); 638 n=StringUtil.replace(n, "-", "", false).toLowerCase(); 639 if(n.equalsIgnoreCase(name.getLowerString())) return attr.getValue(); 640 } 641 642 } 643 644 if(value==null) return defaultValue; 645 return value; 646 } 647 648 private String _get(String name) { 649 if(el.hasAttribute(name)) return el.getAttribute(name); 650 return null; 651 } 652 } 653