001 package railo.runtime.orm.hibernate; 002 003 import java.sql.DatabaseMetaData; 004 import java.sql.ResultSet; 005 import java.sql.SQLException; 006 import java.util.ArrayList; 007 import java.util.HashMap; 008 import java.util.Iterator; 009 import java.util.List; 010 import java.util.Map; 011 import java.util.Map.Entry; 012 013 import org.hibernate.EntityMode; 014 import org.hibernate.SessionFactory; 015 import org.hibernate.cfg.Configuration; 016 import org.hibernate.engine.SessionFactoryImplementor; 017 import org.hibernate.engine.query.QueryPlanCache; 018 import org.hibernate.event.EventListeners; 019 import org.hibernate.event.PostDeleteEventListener; 020 import org.hibernate.event.PostInsertEventListener; 021 import org.hibernate.event.PostLoadEventListener; 022 import org.hibernate.event.PostUpdateEventListener; 023 import org.hibernate.event.PreDeleteEventListener; 024 import org.hibernate.event.PreLoadEventListener; 025 import org.hibernate.tuple.entity.EntityTuplizerFactory; 026 import org.w3c.dom.Document; 027 import org.w3c.dom.Element; 028 029 import railo.commons.db.DBUtil; 030 import railo.commons.io.IOUtil; 031 import railo.commons.io.res.Resource; 032 import railo.commons.lang.StringUtil; 033 import railo.runtime.Component; 034 import railo.runtime.ComponentPro; 035 import railo.runtime.PageContext; 036 import railo.runtime.config.ConfigWebImpl; 037 import railo.runtime.db.DataSource; 038 import railo.runtime.db.DatasourceConnection; 039 import railo.runtime.db.DatasourceConnectionPool; 040 import railo.runtime.exp.ExpressionException; 041 import railo.runtime.exp.PageException; 042 import railo.runtime.listener.ApplicationContextPro; 043 import railo.runtime.op.Caster; 044 import railo.runtime.orm.ORMConfiguration; 045 import railo.runtime.orm.ORMEngine; 046 import railo.runtime.orm.ORMException; 047 import railo.runtime.orm.ORMSession; 048 import railo.runtime.orm.ORMUtil; 049 import railo.runtime.orm.hibernate.event.AllEventListener; 050 import railo.runtime.orm.hibernate.event.EventListener; 051 import railo.runtime.orm.hibernate.event.InterceptorImpl; 052 import railo.runtime.orm.hibernate.event.PostDeleteEventListenerImpl; 053 import railo.runtime.orm.hibernate.event.PostInsertEventListenerImpl; 054 import railo.runtime.orm.hibernate.event.PostLoadEventListenerImpl; 055 import railo.runtime.orm.hibernate.event.PostUpdateEventListenerImpl; 056 import railo.runtime.orm.hibernate.event.PreDeleteEventListenerImpl; 057 import railo.runtime.orm.hibernate.event.PreInsertEventListenerImpl; 058 import railo.runtime.orm.hibernate.event.PreLoadEventListenerImpl; 059 import railo.runtime.orm.hibernate.event.PreUpdateEventListenerImpl; 060 import railo.runtime.orm.hibernate.tuplizer.AbstractEntityTuplizerImpl; 061 import railo.runtime.orm.naming.CFCNamingStrategy; 062 import railo.runtime.orm.naming.DefaultNamingStrategy; 063 import railo.runtime.orm.naming.NamingStrategy; 064 import railo.runtime.orm.naming.SmartNamingStrategy; 065 import railo.runtime.text.xml.XMLCaster; 066 import railo.runtime.text.xml.XMLUtil; 067 import railo.runtime.type.CastableStruct; 068 import railo.runtime.type.Collection; 069 import railo.runtime.type.KeyImpl; 070 import railo.runtime.type.Struct; 071 import railo.runtime.type.StructImpl; 072 import railo.runtime.type.util.ArrayUtil; 073 import railo.runtime.type.util.ComponentUtil; 074 import railo.runtime.util.ApplicationContext; 075 076 public class HibernateORMEngine implements ORMEngine { 077 078 079 private static final Collection.Key INIT = KeyImpl.intern("init"); 080 081 private Configuration configuration; 082 083 private SessionFactory _factory; 084 private String datasource; 085 //private Map<String,Long> _cfcids=new HashMap<String, Long>(); 086 //private Map<String,String> _cfcs=new HashMap<String, String>(); 087 private Map<String,CFCInfo> cfcs=new HashMap<String, CFCInfo>(); 088 089 private Struct tableInfo=new StructImpl(); 090 091 092 private QueryPlanCache _queryPlanCache; 093 094 private DataSource ds; 095 096 private List<ComponentPro> arr; 097 098 private Object hash; 099 100 private ORMConfiguration ormConf; 101 102 private NamingStrategy namingStrategy=DefaultNamingStrategy.INSTANCE; 103 104 public HibernateORMEngine() {} 105 106 void checkExistent(PageContext pc,Component cfc) throws ORMException { 107 if(!cfcs.containsKey(id(HibernateCaster.getEntityName(cfc)))) 108 throw new ORMException(this,"there is no mapping definition for component ["+cfc.getAbsName()+"]"); 109 } 110 111 112 113 114 /** 115 * @see railo.runtime.orm.ORMEngine#init(railo.runtime.PageContext) 116 */ 117 public void init(PageContext pc) throws PageException{ 118 getSessionFactory(pc,true); 119 } 120 121 /** 122 * @see railo.runtime.orm.ORMEngine#getSession(railo.runtime.PageContext) 123 */ 124 public ORMSession createSession(PageContext pc) throws PageException { 125 ApplicationContextPro appContext = ((ApplicationContextPro)pc.getApplicationContext()); 126 String dsn=appContext.getORMDatasource(); 127 128 //DatasourceManager manager = pc.getDataSourceManager(); 129 //DatasourceConnection dc=manager.getConnection(pc,dsn, null, null); 130 DatasourceConnection dc = ((ConfigWebImpl)pc.getConfig()).getDatasourceConnectionPool().getDatasourceConnection(pc,pc.getConfig().getDataSource(dsn),null,null); 131 try{ 132 133 return new HibernateORMSession(this,getSessionFactory(pc),dc); 134 } 135 catch(PageException pe){ 136 //manager.releaseConnection(pc, dc);// connection is closed when session ends 137 throw pe; 138 } 139 } 140 141 142 QueryPlanCache getQueryPlanCache(PageContext pc) throws PageException { 143 SessionFactory _old = _factory; 144 SessionFactory _new = getSessionFactory(pc); 145 146 if(_queryPlanCache==null || _old!=_new){ 147 _queryPlanCache=new QueryPlanCache((SessionFactoryImplementor) _new); 148 } 149 return _queryPlanCache; 150 } 151 152 /** 153 * @see railo.runtime.orm.ORMEngine#getSessionFactory(railo.runtime.PageContext) 154 */ 155 public SessionFactory getSessionFactory(PageContext pc) throws PageException{ 156 return getSessionFactory(pc,false); 157 } 158 159 public boolean reload(PageContext pc, boolean force) throws PageException { 160 if(force) { 161 if(_factory!=null){ 162 _factory.close(); 163 _factory=null; 164 configuration=null; 165 } 166 } 167 else { 168 Object h = hash((ApplicationContextPro)pc.getApplicationContext()); 169 if(this.hash.equals(h))return false; 170 } 171 172 getSessionFactory(pc,true); 173 return true; 174 } 175 176 177 private synchronized SessionFactory getSessionFactory(PageContext pc,boolean init) throws PageException { 178 ApplicationContextPro appContext = ((ApplicationContextPro)pc.getApplicationContext()); 179 if(!appContext.isORMEnabled()) 180 throw new ORMException(this,"ORM is not enabled in application.cfc/cfapplication"); 181 182 this.hash=hash(appContext); 183 184 // datasource 185 String dsn=appContext.getORMDatasource(); 186 if(StringUtil.isEmpty(dsn)) 187 throw new ORMException(this,"missing datasource defintion in application.cfc/cfapplication"); 188 if(!dsn.equalsIgnoreCase(datasource)){ 189 configuration=null; 190 if(_factory!=null) _factory.close(); 191 _factory=null; 192 datasource=dsn.toLowerCase(); 193 } 194 195 // config 196 ormConf = appContext.getORMConfiguration(); 197 198 //List<Component> arr = null; 199 arr=null; 200 if(init){ 201 if(ormConf.autogenmap()){ 202 arr = HibernateSessionFactory.loadComponents(pc, this, ormConf); 203 cfcs.clear(); 204 } 205 else 206 throw new HibernateException(this,"orm setting autogenmap=false is not supported yet"); 207 } 208 209 // load entities 210 if(!ArrayUtil.isEmpty(arr)) { 211 loadNamingStrategy(ormConf); 212 213 214 DatasourceConnectionPool pool = ((ConfigWebImpl)pc.getConfig()).getDatasourceConnectionPool(); 215 DatasourceConnection dc = pool.getDatasourceConnection(pc,pc.getConfig().getDataSource(dsn),null,null); 216 //DataSourceManager manager = pc.getDataSourceManager(); 217 //DatasourceConnection dc=manager.getConnection(pc,dsn, null, null); 218 this.ds=dc.getDatasource(); 219 try { 220 Iterator<ComponentPro> it = arr.iterator(); 221 while(it.hasNext()){ 222 createMapping(pc,it.next(),dc,ormConf); 223 } 224 } 225 finally { 226 pool.releaseDatasourceConnection(dc); 227 //manager.releaseConnection(pc,dc); 228 } 229 if(arr.size()!=cfcs.size()){ 230 ComponentPro cfc; 231 String name,lcName; 232 Map<String,String> names=new HashMap<String,String>(); 233 Iterator<ComponentPro> it = arr.iterator(); 234 while(it.hasNext()){ 235 cfc=it.next(); 236 name=HibernateCaster.getEntityName(cfc); 237 lcName=name.toLowerCase(); 238 if(names.containsKey(lcName)) 239 throw new ORMException(this,"Entity Name ["+name+"] is ambigous, ["+names.get(lcName)+"] and ["+cfc.getPageSource().getDisplayPath()+"] use the same entity name."); 240 names.put(lcName,cfc.getPageSource().getDisplayPath()); 241 } 242 } 243 } 244 arr=null; 245 if(configuration!=null) return _factory; 246 247 //MUST 248 //cacheconfig 249 //cacheprovider 250 //... 251 252 String mappings=HibernateSessionFactory.createMappings(this,cfcs); 253 254 DatasourceConnectionPool pool = ((ConfigWebImpl)pc.getConfig()).getDatasourceConnectionPool(); 255 DatasourceConnection dc = pool.getDatasourceConnection(pc,pc.getConfig().getDataSource(dsn),null,null); 256 try{ 257 configuration = HibernateSessionFactory.createConfiguration(this,mappings,dc,ormConf); 258 } 259 catch (Exception e) { 260 throw Caster.toPageException(e); 261 } 262 finally { 263 pool.releaseDatasourceConnection(dc); 264 } 265 266 addEventListeners(pc, configuration,ormConf,cfcs); 267 268 EntityTuplizerFactory tuplizerFactory = configuration.getEntityTuplizerFactory(); 269 //tuplizerFactory.registerDefaultTuplizerClass(EntityMode.MAP, CFCEntityTuplizer.class); 270 //tuplizerFactory.registerDefaultTuplizerClass(EntityMode.MAP, MapEntityTuplizer.class); 271 tuplizerFactory.registerDefaultTuplizerClass(EntityMode.MAP, AbstractEntityTuplizerImpl.class); 272 tuplizerFactory.registerDefaultTuplizerClass(EntityMode.POJO, AbstractEntityTuplizerImpl.class); 273 //tuplizerFactory.registerDefaultTuplizerClass(EntityMode.POJO, AbstractEntityTuplizerImpl.class); 274 275 //configuration.setEntityResolver(new CFCEntityResolver()); 276 //configuration.setEntityNotFoundDelegate(new EntityNotFoundDelegate()); 277 278 279 280 return _factory = configuration.buildSessionFactory(); 281 } 282 283 private void loadNamingStrategy(ORMConfiguration ormConf) throws PageException { 284 String strNamingStrategy=ormConf.namingStrategy(); 285 if(StringUtil.isEmpty(strNamingStrategy,true)) { 286 namingStrategy=DefaultNamingStrategy.INSTANCE; 287 } 288 else { 289 strNamingStrategy=strNamingStrategy.trim(); 290 if("default".equalsIgnoreCase(strNamingStrategy)) 291 namingStrategy=DefaultNamingStrategy.INSTANCE; 292 else if("smart".equalsIgnoreCase(strNamingStrategy)) 293 namingStrategy=SmartNamingStrategy.INSTANCE; 294 else 295 namingStrategy=new CFCNamingStrategy(strNamingStrategy); 296 } 297 } 298 299 private static void addEventListeners(PageContext pc, Configuration config,ORMConfiguration ormConfig, Map<String, CFCInfo> cfcs) throws PageException { 300 if(!ormConfig.eventHandling()) return; 301 String eventHandler = ormConfig.eventHandler(); 302 AllEventListener listener=null; 303 if(!StringUtil.isEmpty(eventHandler,true)){ 304 //try { 305 Component c = pc.loadComponent(eventHandler.trim()); 306 307 listener = new AllEventListener(c); 308 //config.setInterceptor(listener); 309 //}catch (PageException e) {e.printStackTrace();} 310 } 311 config.setInterceptor(new InterceptorImpl(listener)); 312 EventListeners listeners = config.getEventListeners(); 313 314 // post delete 315 List<EventListener> 316 list=merge(listener,cfcs,EventListener.POST_DELETE); 317 listeners.setPostDeleteEventListeners(list.toArray(new PostDeleteEventListener[list.size()])); 318 319 // post insert 320 list=merge(listener,cfcs,EventListener.POST_INSERT); 321 listeners.setPostInsertEventListeners(list.toArray(new PostInsertEventListener[list.size()])); 322 323 // post update 324 list=merge(listener,cfcs,EventListener.POST_UPDATE); 325 listeners.setPostUpdateEventListeners(list.toArray(new PostUpdateEventListener[list.size()])); 326 327 // post load 328 list=merge(listener,cfcs,EventListener.POST_LOAD); 329 listeners.setPostLoadEventListeners(list.toArray(new PostLoadEventListener[list.size()])); 330 331 // pre delete 332 list=merge(listener,cfcs,EventListener.PRE_DELETE); 333 listeners.setPreDeleteEventListeners(list.toArray(new PreDeleteEventListener[list.size()])); 334 335 // pre insert 336 //list=merge(listener,cfcs,EventListener.PRE_INSERT); 337 //listeners.setPreInsertEventListeners(list.toArray(new PreInsertEventListener[list.size()])); 338 339 // pre load 340 list=merge(listener,cfcs,EventListener.PRE_LOAD); 341 listeners.setPreLoadEventListeners(list.toArray(new PreLoadEventListener[list.size()])); 342 343 // pre update 344 //list=merge(listener,cfcs,EventListener.PRE_UPDATE); 345 //listeners.setPreUpdateEventListeners(list.toArray(new PreUpdateEventListener[list.size()])); 346 } 347 348 private static List<EventListener> merge(EventListener listener, Map<String, CFCInfo> cfcs, Collection.Key eventType) { 349 List<EventListener> list=new ArrayList<EventListener>(); 350 351 352 Iterator<Entry<String, CFCInfo>> it = cfcs.entrySet().iterator(); 353 Entry<String, CFCInfo> entry; 354 Component cfc; 355 while(it.hasNext()){ 356 entry = it.next(); 357 cfc = entry.getValue().getCFC(); 358 if(EventListener.hasEventType(cfc,eventType)) { 359 if(EventListener.POST_DELETE.equals(eventType)) 360 list.add(new PostDeleteEventListenerImpl(cfc)); 361 if(EventListener.POST_INSERT.equals(eventType)) 362 list.add(new PostInsertEventListenerImpl(cfc)); 363 if(EventListener.POST_LOAD.equals(eventType)) 364 list.add(new PostLoadEventListenerImpl(cfc)); 365 if(EventListener.POST_UPDATE.equals(eventType)) 366 list.add(new PostUpdateEventListenerImpl(cfc)); 367 368 if(EventListener.PRE_DELETE.equals(eventType)) 369 list.add(new PreDeleteEventListenerImpl(cfc)); 370 if(EventListener.PRE_INSERT.equals(eventType)) 371 list.add(new PreInsertEventListenerImpl(cfc)); 372 if(EventListener.PRE_LOAD.equals(eventType)) 373 list.add(new PreLoadEventListenerImpl(cfc)); 374 if(EventListener.PRE_UPDATE.equals(eventType)) 375 list.add(new PreUpdateEventListenerImpl(cfc)); 376 } 377 } 378 379 // general listener 380 if(listener!=null && EventListener.hasEventType(listener.getCFC(),eventType)) 381 list.add(listener); 382 383 return list; 384 } 385 386 private Object hash(ApplicationContextPro appContext) { 387 String hash=appContext.getORMDatasource()+":"+appContext.getORMConfiguration().hash(); 388 //print.ds(hash); 389 return hash; 390 } 391 392 public void createMapping(PageContext pc,Component cfc, DatasourceConnection dc, ORMConfiguration ormConf) throws PageException { 393 ComponentPro cfcp=ComponentUtil.toComponentPro(cfc); 394 String id=id(HibernateCaster.getEntityName(cfcp)); 395 CFCInfo info=cfcs.get(id); 396 //Long modified=cfcs.get(id); 397 String xml; 398 long cfcCompTime = ComponentUtil.getCompileTime(pc,cfcp.getPageSource()); 399 if(info==null || (ORMUtil.equals(info.getCFC(),cfcp) )) {//&& info.getModified()!=cfcCompTime 400 StringBuilder sb=new StringBuilder(); 401 402 long xmlLastMod = loadMapping(sb,ormConf, cfcp); 403 Element root; 404 // create maaping 405 if(true || xmlLastMod< cfcCompTime) {//MUSTMUST 406 configuration=null; 407 Document doc=null; 408 try { 409 doc=XMLUtil.newDocument(); 410 }catch(Throwable t){t.printStackTrace();} 411 412 root=doc.createElement("hibernate-mapping"); 413 doc.appendChild(root); 414 pc.addPageSource(cfcp.getPageSource(), true); 415 try{ 416 HBMCreator.createXMLMapping(pc,dc,cfcp,ormConf,root, this); 417 } 418 finally{ 419 pc.removeLastPageSource(true); 420 } 421 xml=XMLCaster.toString(root.getChildNodes(),true); 422 saveMapping(ormConf,cfcp,root); 423 } 424 // load 425 else { 426 xml=sb.toString(); 427 root=Caster.toXML(xml).getOwnerDocument().getDocumentElement(); 428 /*print.o("1+++++++++++++++++++++++++++++++++++++++++"); 429 print.o(xml); 430 print.o("2+++++++++++++++++++++++++++++++++++++++++"); 431 print.o(root); 432 print.o("3+++++++++++++++++++++++++++++++++++++++++");*/ 433 434 } 435 cfcs.put(id, new CFCInfo(ComponentUtil.getCompileTime(pc,cfcp.getPageSource()),xml,cfcp)); 436 437 } 438 439 } 440 441 private static void saveMapping(ORMConfiguration ormConf, Component cfc, Element hm) throws ExpressionException { 442 if(ormConf.saveMapping()){ 443 Resource res=ComponentUtil.toComponentPro(cfc).getPageSource().getPhyscalFile(); 444 if(res!=null){ 445 res=res.getParentResource().getRealResource(res.getName()+".hbm.xml"); 446 try{ 447 IOUtil.write(res, 448 XMLCaster.toString(hm,false, 449 HibernateSessionFactory.HIBERNATE_3_PUBLIC_ID, 450 HibernateSessionFactory.HIBERNATE_3_SYSTEM_ID, 451 HibernateSessionFactory.HIBERNATE_3_ENCODING), HibernateSessionFactory.HIBERNATE_3_ENCODING, false); 452 } 453 catch(Exception e){} 454 } 455 } 456 } 457 458 private static long loadMapping(StringBuilder sb,ORMConfiguration ormConf, Component cfc) throws ExpressionException { 459 460 Resource res=ComponentUtil.toComponentPro(cfc).getPageSource().getPhyscalFile(); 461 if(res!=null){ 462 res=res.getParentResource().getRealResource(res.getName()+".hbm.xml"); 463 try{ 464 sb.append(IOUtil.toString(res, "UTF-8")); 465 return res.lastModified(); 466 } 467 catch(Exception e){} 468 } 469 return 0; 470 } 471 472 /** 473 * @see railo.runtime.orm.ORMEngine#getMode() 474 */ 475 public int getMode() { 476 //MUST impl 477 return MODE_LAZY; 478 } 479 480 public DataSource getDataSource(){ 481 return ds; 482 } 483 484 /** 485 * @see railo.runtime.orm.ORMEngine#getLabel() 486 */ 487 public String getLabel() { 488 return "Hibernate"; 489 } 490 491 public Struct getTableInfo(DatasourceConnection dc, String tableName,ORMEngine engine) throws PageException { 492 Collection.Key keyTableName=KeyImpl.init(tableName); 493 Struct columnsInfo = (Struct) tableInfo.get(keyTableName,null); 494 if(columnsInfo!=null) return columnsInfo; 495 496 columnsInfo = checkTable(dc,tableName,engine); 497 tableInfo.setEL(keyTableName,columnsInfo); 498 return columnsInfo; 499 } 500 501 private static Struct checkTable(DatasourceConnection dc, String tableName, ORMEngine engine) throws PageException { 502 String dbName=dc.getDatasource().getDatabase(); 503 try { 504 505 DatabaseMetaData md = dc.getConnection().getMetaData(); 506 Struct rows=checkTableFill(md,dbName,tableName); 507 if(rows.size()==0) { 508 String tableName2 = checkTableValidate(md,dbName,tableName); 509 if(tableName2!=null)rows=checkTableFill(md,dbName,tableName2); 510 } 511 512 if(rows.size()==0) { 513 //ORMUtil.printError("there is no table with name ["+tableName+"] defined", engine); 514 return null; 515 } 516 return rows; 517 } catch (SQLException e) { 518 throw Caster.toPageException(e); 519 } 520 } 521 522 523 524 private static Struct checkTableFill(DatabaseMetaData md, String dbName, String tableName) throws SQLException, PageException { 525 Struct rows=new CastableStruct(tableName,Struct.TYPE_LINKED); 526 ResultSet columns = md.getColumns(dbName, null, tableName, null); 527 //print.o(new QueryImpl(columns,"")); 528 try{ 529 String name; 530 Object nullable; 531 while(columns.next()) { 532 name=columns.getString("COLUMN_NAME"); 533 534 nullable=columns.getObject("IS_NULLABLE"); 535 rows.setEL(KeyImpl.init(name),new ColumnInfo( 536 name, 537 columns.getInt("DATA_TYPE"), 538 columns.getString("TYPE_NAME"), 539 columns.getInt("COLUMN_SIZE"), 540 Caster.toBooleanValue(nullable) 541 )); 542 } 543 } 544 finally { 545 DBUtil.closeEL(columns); 546 }// Table susid defined for cfc susid does not exist. 547 548 return rows; 549 } 550 551 private static String checkTableValidate(DatabaseMetaData md, String dbName,String tableName) { 552 553 ResultSet tables=null; 554 try{ 555 tables = md.getTables(dbName, null, null, null); 556 String name; 557 while(tables.next()) { 558 name=tables.getString("TABLE_NAME"); 559 if(name.equalsIgnoreCase(tableName) && StringUtil.indexOfIgnoreCase(tables.getString("TABLE_TYPE"), "SYSTEM")==-1) 560 return name; 561 } 562 } 563 catch(Throwable t){} 564 finally { 565 DBUtil.closeEL(tables); 566 } 567 return null; 568 569 570 571 } 572 573 /** 574 * @see railo.runtime.orm.ORMEngine#getConfiguration(railo.runtime.PageContext) 575 */ 576 public ORMConfiguration getConfiguration(PageContext pc) { 577 ApplicationContext ac = pc.getApplicationContext(); 578 if(!(ac instanceof ApplicationContextPro)) 579 return null; 580 ApplicationContextPro acp=(ApplicationContextPro) ac; 581 if(!acp.isORMEnabled()) 582 return null; 583 return acp.getORMConfiguration(); 584 } 585 586 /** 587 * @param pc 588 * @param session 589 * @param entityName name of the entity to get 590 * @param unique create a unique version that can be manipulated 591 * @param init call the nit method of the cfc or not 592 * @return 593 * @throws PageException 594 */ 595 public Component create(PageContext pc, HibernateORMSession session,String entityName, boolean unique) throws PageException { 596 597 // get existing entity 598 ComponentPro cfc = _create(pc,entityName,unique); 599 if(cfc!=null)return cfc; 600 601 // reinit ORMEngine 602 SessionFactory _old = _factory; 603 SessionFactory _new = getSessionFactory(pc,true); 604 if(_old!=_new){ 605 session.resetSession(_new); 606 cfc = _create(pc,entityName,unique); 607 if(cfc!=null)return cfc; 608 } 609 610 611 612 ApplicationContextPro appContext = ((ApplicationContextPro)pc.getApplicationContext()); 613 ORMConfiguration ormConf = appContext.getORMConfiguration(); 614 Resource[] locations = ormConf.getCfcLocations(); 615 616 throw new ORMException( 617 "No entity (persitent component) with name ["+entityName+"] found, available entities are ["+railo.runtime.type.List.arrayToList(getEntityNames(), ", ")+"] ", 618 "component are searched in the following directories ["+toString(locations)+"]"); 619 620 621 } 622 623 624 private String toString(Resource[] locations) { 625 if(locations==null) return ""; 626 StringBuilder sb=new StringBuilder(); 627 for(int i=0;i<locations.length;i++){ 628 if(i>0) sb.append(", "); 629 sb.append(locations[i].getAbsolutePath()); 630 } 631 return sb.toString(); 632 } 633 634 private ComponentPro _create(PageContext pc, String entityName, boolean unique) throws PageException { 635 CFCInfo info = cfcs.get(id(entityName)); 636 if(info!=null) { 637 ComponentPro cfc = info.getCFC(); 638 if(unique){ 639 cfc=(ComponentPro)cfc.duplicate(false); 640 if(cfc.contains(pc,INIT))cfc.call(pc, "init",new Object[]{}); 641 } 642 return cfc; 643 } 644 return null; 645 } 646 647 public static String id(String id) { 648 return id.toLowerCase().trim(); 649 } 650 651 public Component getEntityByCFCName(String cfcName,boolean unique) throws PageException { 652 String name=cfcName; 653 int pointIndex=cfcName.lastIndexOf('.'); 654 if(pointIndex!=-1) { 655 name=cfcName.substring(pointIndex+1); 656 } 657 else 658 cfcName=null; 659 660 661 662 ComponentPro cfc; 663 String[] names=null; 664 // search array (array exist when cfcs is in generation) 665 666 if(arr!=null){ 667 names=new String[arr.size()]; 668 int index=0; 669 Iterator<ComponentPro> it2 = arr.iterator(); 670 while(it2.hasNext()){ 671 cfc=it2.next(); 672 names[index++]=cfc.getName(); 673 if(isEntity(cfc,cfcName,name)) //if(cfc.equalTo(name)) 674 return unique?(Component)cfc.duplicate(false):cfc; 675 } 676 } 677 else { 678 // search cfcs 679 Iterator<Entry<String, CFCInfo>> it = cfcs.entrySet().iterator(); 680 Entry<String, CFCInfo> entry; 681 while(it.hasNext()){ 682 entry=it.next(); 683 cfc=entry.getValue().getCFC(); 684 if(isEntity(cfc,cfcName,name)) //if(cfc.instanceOf(name)) 685 return unique?(Component)cfc.duplicate(false):cfc; 686 687 //if(name.equalsIgnoreCase(HibernateCaster.getEntityName(cfc))) 688 // return cfc; 689 } 690 names=cfcs.keySet().toArray(new String[cfcs.size()]); 691 } 692 693 // search by entityname //TODO is this ok? 694 CFCInfo info = cfcs.get(name.toLowerCase()); 695 if(info!=null) { 696 cfc=info.getCFC(); 697 return unique?(Component)cfc.duplicate(false):cfc; 698 } 699 700 throw new ORMException(this,"entity ["+name+"] "+(StringUtil.isEmpty(cfcName)?"":"with cfc name ["+cfcName+"] ")+"does not exist, existing entities are ["+railo.runtime.type.List.arrayToList(names, ", ")+"]"); 701 702 } 703 704 705 private boolean isEntity(ComponentPro cfc, String cfcName, String name) { 706 if(!StringUtil.isEmpty(cfcName)) { 707 if(cfc.equalTo(cfcName)) return true; 708 709 if(cfcName.indexOf('.')!=-1) { 710 String path=cfcName.replace('.', '/')+".cfc"; 711 Resource[] locations = ormConf.getCfcLocations(); 712 for(int i=0;i<locations.length;i++){ 713 if(locations[i].getRealResource(path).equals(cfc.getPageSource().getFile())) 714 return true; 715 } 716 return false; 717 } 718 } 719 720 if(cfc.equalTo(name)) return true; 721 return name.equalsIgnoreCase(HibernateCaster.getEntityName(cfc)); 722 } 723 724 public Component getEntityByEntityName(String entityName,boolean unique) throws PageException { 725 ComponentPro cfc; 726 727 728 CFCInfo info = cfcs.get(entityName.toLowerCase()); 729 if(info!=null) { 730 cfc=info.getCFC(); 731 return unique?(Component)cfc.duplicate(false):cfc; 732 } 733 734 if(arr!=null){ 735 Iterator<ComponentPro> it2 = arr.iterator(); 736 while(it2.hasNext()){ 737 cfc=it2.next(); 738 if(HibernateCaster.getEntityName(cfc).equalsIgnoreCase(entityName)) 739 return unique?(Component)cfc.duplicate(false):cfc; 740 } 741 } 742 743 744 745 throw new ORMException(this,"entity ["+entityName+"] does not exist"); 746 747 } 748 749 750 751 public String[] getEntityNames() { 752 Iterator<Entry<String, CFCInfo>> it = cfcs.entrySet().iterator(); 753 String[] names=new String[cfcs.size()]; 754 int index=0; 755 while(it.hasNext()){ 756 names[index++]=HibernateCaster.getEntityName(it.next().getValue().getCFC()); 757 //names[index++]=it.next().getValue().getCFC().getName(); 758 } 759 return names; 760 761 //return cfcs.keySet().toArray(new String[cfcs.size()]); 762 } 763 764 public String convertTableName(String tableName) { 765 if(tableName==null) return null; 766 //print.o("table:"+namingStrategy.getType()+":"+tableName+":"+namingStrategy.convertTableName(tableName)); 767 return namingStrategy.convertTableName(tableName); 768 } 769 770 public String convertColumnName(String columnName) { 771 if(columnName==null) return null; 772 //print.o("column:"+namingStrategy.getType()+":"+columnName+":"+namingStrategy.convertTableName(columnName)); 773 return namingStrategy.convertColumnName(columnName); 774 } 775 776 777 778 } 779 class CFCInfo { 780 private String xml; 781 private long modified; 782 private ComponentPro cfc; 783 784 public CFCInfo(long modified, String xml, ComponentPro cfc) { 785 this.modified=modified; 786 this.xml=xml; 787 this.cfc=cfc; 788 } 789 /** 790 * @return the cfc 791 */ 792 public ComponentPro getCFC() { 793 return cfc; 794 } 795 /** 796 * @return the xml 797 */ 798 public String getXML() { 799 return xml; 800 } 801 /** 802 * @return the modified 803 */ 804 public long getModified() { 805 return modified; 806 } 807 808 } 809