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.PageContext; 035 import railo.runtime.PageContextImpl; 036 import railo.runtime.config.ConfigWebImpl; 037 import railo.runtime.config.Constants; 038 import railo.runtime.db.DataSource; 039 import railo.runtime.db.DataSourcePro; 040 import railo.runtime.db.DatasourceConnection; 041 import railo.runtime.db.DatasourceConnectionPool; 042 import railo.runtime.exp.PageException; 043 import railo.runtime.listener.ApplicationContext; 044 import railo.runtime.listener.ApplicationContextPro; 045 import railo.runtime.op.Caster; 046 import railo.runtime.op.Duplicator; 047 import railo.runtime.orm.ORMConfiguration; 048 import railo.runtime.orm.ORMEngine; 049 import railo.runtime.orm.ORMException; 050 import railo.runtime.orm.ORMSession; 051 import railo.runtime.orm.ORMUtil; 052 import railo.runtime.orm.hibernate.event.AllEventListener; 053 import railo.runtime.orm.hibernate.event.EventListener; 054 import railo.runtime.orm.hibernate.event.InterceptorImpl; 055 import railo.runtime.orm.hibernate.event.PostDeleteEventListenerImpl; 056 import railo.runtime.orm.hibernate.event.PostInsertEventListenerImpl; 057 import railo.runtime.orm.hibernate.event.PostLoadEventListenerImpl; 058 import railo.runtime.orm.hibernate.event.PostUpdateEventListenerImpl; 059 import railo.runtime.orm.hibernate.event.PreDeleteEventListenerImpl; 060 import railo.runtime.orm.hibernate.event.PreInsertEventListenerImpl; 061 import railo.runtime.orm.hibernate.event.PreLoadEventListenerImpl; 062 import railo.runtime.orm.hibernate.event.PreUpdateEventListenerImpl; 063 import railo.runtime.orm.hibernate.tuplizer.AbstractEntityTuplizerImpl; 064 import railo.runtime.orm.naming.CFCNamingStrategy; 065 import railo.runtime.orm.naming.DefaultNamingStrategy; 066 import railo.runtime.orm.naming.NamingStrategy; 067 import railo.runtime.orm.naming.SmartNamingStrategy; 068 import railo.runtime.text.xml.XMLCaster; 069 import railo.runtime.text.xml.XMLUtil; 070 import railo.runtime.type.CastableStruct; 071 import railo.runtime.type.Collection; 072 import railo.runtime.type.KeyImpl; 073 import railo.runtime.type.Struct; 074 import railo.runtime.type.StructImpl; 075 import railo.runtime.type.util.ArrayUtil; 076 import railo.runtime.type.util.ComponentUtil; 077 078 public class HibernateORMEngine implements ORMEngine { 079 080 081 private static final Collection.Key INIT = KeyImpl.intern("init"); 082 083 private Configuration configuration; 084 085 private SessionFactory _factory; 086 private String _datasource; 087 //private Map<String,Long> _cfcids=new HashMap<String, Long>(); 088 //private Map<String,String> _cfcs=new HashMap<String, String>(); 089 private Map<String,CFCInfo> cfcs=new HashMap<String, CFCInfo>(); 090 091 private Struct tableInfo=new StructImpl(); 092 093 094 private QueryPlanCache _queryPlanCache; 095 096 private DataSource ds; 097 098 private List<Component> arr; 099 100 private Object hash; 101 102 private ORMConfiguration ormConf; 103 104 private NamingStrategy namingStrategy=DefaultNamingStrategy.INSTANCE; 105 106 public HibernateORMEngine() {} 107 108 void checkExistent(PageContext pc,Component cfc) throws ORMException { 109 if(!cfcs.containsKey(id(HibernateCaster.getEntityName(cfc)))) 110 throw new ORMException(this,"there is no mapping definition for component ["+cfc.getAbsName()+"]"); 111 } 112 113 114 115 116 @Override 117 public void init(PageContext pc) throws PageException{ 118 getSessionFactory(pc,true); 119 } 120 121 @Override 122 public ORMSession createSession(PageContext pc) throws PageException { 123 ApplicationContextPro appContext = (ApplicationContextPro) pc.getApplicationContext(); 124 Object o=appContext.getORMDataSource(); 125 126 DataSource ds=o instanceof DataSource?(DataSource)o:((PageContextImpl)pc).getDataSource(Caster.toString(o)); 127 128 DatasourceConnection dc = ((ConfigWebImpl)pc.getConfig()).getDatasourceConnectionPool().getDatasourceConnection(pc,ds,null,null); 129 try{ 130 131 return new HibernateORMSession(this,getSessionFactory(pc),dc); 132 } 133 catch(PageException pe){ 134 //manager.releaseConnection(pc, dc);// connection is closed when session ends 135 throw pe; 136 } 137 } 138 139 140 QueryPlanCache getQueryPlanCache(PageContext pc) throws PageException { 141 SessionFactory _old = _factory; 142 SessionFactory _new = getSessionFactory(pc); 143 144 if(_queryPlanCache==null || _old!=_new){ 145 _queryPlanCache=new QueryPlanCache((SessionFactoryImplementor) _new); 146 } 147 return _queryPlanCache; 148 } 149 150 @Override 151 public SessionFactory getSessionFactory(PageContext pc) throws PageException{ 152 return getSessionFactory(pc,false); 153 } 154 155 public boolean reload(PageContext pc, boolean force) throws PageException { 156 if(force) { 157 if(_factory!=null){ 158 _factory.close(); 159 _factory=null; 160 configuration=null; 161 } 162 } 163 else { 164 Object h = hash(pc); 165 if(this.hash.equals(h))return false; 166 } 167 168 getSessionFactory(pc,true); 169 return true; 170 } 171 172 173 private synchronized SessionFactory getSessionFactory(PageContext pc,boolean init) throws PageException { 174 ApplicationContextPro appContext = (ApplicationContextPro) pc.getApplicationContext(); 175 if(!appContext.isORMEnabled()) 176 throw new ORMException(this,"ORM is not enabled in "+Constants.APP_CFC+"/"+Constants.CFAPP_NAME); 177 178 this.hash=hash(pc); 179 180 // datasource 181 Object o=appContext.getORMDataSource(); 182 if(StringUtil.isEmpty(o)) 183 throw new ORMException(this,"missing datasource defintion in "+Constants.APP_CFC+"/"+Constants.CFAPP_NAME); 184 185 DataSource _ds = o instanceof DataSource?(DataSource)o:((PageContextImpl)pc).getDataSource(Caster.toString(o)); 186 187 188 if(ds==null || !ds.equals(_ds)){ 189 configuration=null; 190 if(_factory!=null) _factory.close(); 191 _factory=null; 192 ds=_ds; 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,ds,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<Component> 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 Component cfc; 231 String name,lcName; 232 Map<String,String> names=new HashMap<String,String>(); 233 Iterator<Component> 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,ds,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(PageContext pc) throws PageException { 387 ApplicationContextPro appContext=(ApplicationContextPro) pc.getApplicationContext(); 388 Object o=appContext.getORMDataSource(); 389 DataSource ds; 390 if(o instanceof DataSource) ds=(DataSource) o; 391 else ds=((PageContextImpl)pc).getDataSource(Caster.toString(o)); 392 if(ds instanceof DataSourcePro) 393 return hash=((DataSourcePro)ds).id()+":"+appContext.getORMConfiguration().hash(); 394 395 return ds.getClazz()+":"+ds.getDsnTranslated()+":"+appContext.getORMConfiguration().hash(); 396 } 397 398 public void createMapping(PageContext pc,Component cfc, DatasourceConnection dc, ORMConfiguration ormConf) throws PageException { 399 String id=id(HibernateCaster.getEntityName(cfc)); 400 CFCInfo info=cfcs.get(id); 401 //Long modified=cfcs.get(id); 402 String xml; 403 long cfcCompTime = ComponentUtil.getCompileTime(pc,cfc.getPageSource()); 404 if(info==null || (ORMUtil.equals(info.getCFC(),cfc) )) {//&& info.getModified()!=cfcCompTime 405 StringBuilder sb=new StringBuilder(); 406 407 long xmlLastMod = loadMapping(sb,ormConf, cfc); 408 Element root; 409 // create maaping 410 if(true || xmlLastMod< cfcCompTime) {//MUSTMUST 411 configuration=null; 412 Document doc=null; 413 try { 414 doc=XMLUtil.newDocument(); 415 }catch(Throwable t){t.printStackTrace();} 416 417 root=doc.createElement("hibernate-mapping"); 418 doc.appendChild(root); 419 pc.addPageSource(cfc.getPageSource(), true); 420 try{ 421 HBMCreator.createXMLMapping(pc,dc,cfc,ormConf,root, this); 422 } 423 finally{ 424 pc.removeLastPageSource(true); 425 } 426 xml=XMLCaster.toString(root.getChildNodes(),true,true); 427 saveMapping(ormConf,cfc,root); 428 } 429 // load 430 else { 431 xml=sb.toString(); 432 root=Caster.toXML(xml).getOwnerDocument().getDocumentElement(); 433 /*print.o("1+++++++++++++++++++++++++++++++++++++++++"); 434 print.o(xml); 435 print.o("2+++++++++++++++++++++++++++++++++++++++++"); 436 print.o(root); 437 print.o("3+++++++++++++++++++++++++++++++++++++++++");*/ 438 439 } 440 cfcs.put(id, new CFCInfo(ComponentUtil.getCompileTime(pc,cfc.getPageSource()),xml,cfc)); 441 } 442 443 } 444 445 private static void saveMapping(ORMConfiguration ormConf, Component cfc, Element hm) { 446 if(ormConf.saveMapping()){ 447 Resource res=cfc.getPageSource().getResource(); 448 if(res!=null){ 449 res=res.getParentResource().getRealResource(res.getName()+".hbm.xml"); 450 try{ 451 IOUtil.write(res, 452 XMLCaster.toString(hm,false,true, 453 HibernateSessionFactory.HIBERNATE_3_PUBLIC_ID, 454 HibernateSessionFactory.HIBERNATE_3_SYSTEM_ID, 455 HibernateSessionFactory.HIBERNATE_3_ENCODING), HibernateSessionFactory.HIBERNATE_3_ENCODING, false); 456 } 457 catch(Exception e){} 458 } 459 } 460 } 461 462 private static long loadMapping(StringBuilder sb,ORMConfiguration ormConf, Component cfc) { 463 464 Resource res=cfc.getPageSource().getResource(); 465 if(res!=null){ 466 res=res.getParentResource().getRealResource(res.getName()+".hbm.xml"); 467 try{ 468 sb.append(IOUtil.toString(res, "UTF-8")); 469 return res.lastModified(); 470 } 471 catch(Exception e){} 472 } 473 return 0; 474 } 475 476 @Override 477 public int getMode() { 478 //MUST impl 479 return MODE_LAZY; 480 } 481 482 public DataSource getDataSource(){ 483 return ds; 484 } 485 486 @Override 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 @Override 574 public ORMConfiguration getConfiguration(PageContext pc) { 575 ApplicationContext ac = pc.getApplicationContext(); 576 if(!ac.isORMEnabled()) 577 return null; 578 return ac.getORMConfiguration(); 579 } 580 581 /** 582 * @param pc 583 * @param session 584 * @param entityName name of the entity to get 585 * @param unique create a unique version that can be manipulated 586 * @param init call the nit method of the cfc or not 587 * @return 588 * @throws PageException 589 */ 590 public Component create(PageContext pc, HibernateORMSession session,String entityName, boolean unique) throws PageException { 591 592 // get existing entity 593 Component cfc = _create(pc,entityName,unique); 594 if(cfc!=null)return cfc; 595 596 // reinit ORMEngine 597 SessionFactory _old = _factory; 598 SessionFactory _new = getSessionFactory(pc,true); 599 if(_old!=_new){ 600 session.resetSession(_new); 601 cfc = _create(pc,entityName,unique); 602 if(cfc!=null)return cfc; 603 } 604 605 606 607 ORMConfiguration ormConf = pc.getApplicationContext().getORMConfiguration(); 608 Resource[] locations = ormConf.getCfcLocations(); 609 610 throw new ORMException( 611 "No entity (persitent component) with name ["+entityName+"] found, available entities are ["+railo.runtime.type.util.ListUtil.arrayToList(getEntityNames(), ", ")+"] ", 612 "component are searched in the following directories ["+toString(locations)+"]"); 613 614 } 615 616 617 private String toString(Resource[] locations) { 618 if(locations==null) return ""; 619 StringBuilder sb=new StringBuilder(); 620 for(int i=0;i<locations.length;i++){ 621 if(i>0) sb.append(", "); 622 sb.append(locations[i].getAbsolutePath()); 623 } 624 return sb.toString(); 625 } 626 627 private Component _create(PageContext pc, String entityName, boolean unique) throws PageException { 628 CFCInfo info = cfcs.get(id(entityName)); 629 if(info!=null) { 630 Component cfc = info.getCFC(); 631 if(unique){ 632 cfc=(Component)Duplicator.duplicate(cfc,false); 633 if(cfc.contains(pc,INIT))cfc.call(pc, "init",new Object[]{}); 634 } 635 return cfc; 636 } 637 return null; 638 } 639 640 public static String id(String id) { 641 return id.toLowerCase().trim(); 642 } 643 644 public Component getEntityByCFCName(String cfcName,boolean unique) throws PageException { 645 String name=cfcName; 646 int pointIndex=cfcName.lastIndexOf('.'); 647 if(pointIndex!=-1) { 648 name=cfcName.substring(pointIndex+1); 649 } 650 else 651 cfcName=null; 652 653 654 655 Component cfc; 656 String[] names=null; 657 // search array (array exist when cfcs is in generation) 658 659 if(arr!=null){ 660 names=new String[arr.size()]; 661 int index=0; 662 Iterator<Component> it2 = arr.iterator(); 663 while(it2.hasNext()){ 664 cfc=it2.next(); 665 names[index++]=cfc.getName(); 666 if(isEntity(cfc,cfcName,name)) //if(cfc.equalTo(name)) 667 return unique?(Component)Duplicator.duplicate(cfc,false):cfc; 668 } 669 } 670 else { 671 // search cfcs 672 Iterator<Entry<String, CFCInfo>> it = cfcs.entrySet().iterator(); 673 Entry<String, CFCInfo> entry; 674 while(it.hasNext()){ 675 entry=it.next(); 676 cfc=entry.getValue().getCFC(); 677 if(isEntity(cfc,cfcName,name)) //if(cfc.instanceOf(name)) 678 return unique?(Component)Duplicator.duplicate(cfc,false):cfc; 679 680 //if(name.equalsIgnoreCase(HibernateCaster.getEntityName(cfc))) 681 // return cfc; 682 } 683 names=cfcs.keySet().toArray(new String[cfcs.size()]); 684 } 685 686 // search by entityname //TODO is this ok? 687 CFCInfo info = cfcs.get(name.toLowerCase()); 688 if(info!=null) { 689 cfc=info.getCFC(); 690 return unique?(Component)Duplicator.duplicate(cfc,false):cfc; 691 } 692 693 throw new ORMException(this,"entity ["+name+"] "+(StringUtil.isEmpty(cfcName)?"":"with cfc name ["+cfcName+"] ")+"does not exist, existing entities are ["+railo.runtime.type.util.ListUtil.arrayToList(names, ", ")+"]"); 694 695 } 696 697 698 private boolean isEntity(Component cfc, String cfcName, String name) { 699 if(!StringUtil.isEmpty(cfcName)) { 700 if(cfc.equalTo(cfcName)) return true; 701 702 if(cfcName.indexOf('.')!=-1) { 703 String path=cfcName.replace('.', '/')+".cfc"; 704 Resource[] locations = ormConf.getCfcLocations(); 705 for(int i=0;i<locations.length;i++){ 706 if(locations[i].getRealResource(path).equals(cfc.getPageSource().getResource())) 707 return true; 708 } 709 return false; 710 } 711 } 712 713 if(cfc.equalTo(name)) return true; 714 return name.equalsIgnoreCase(HibernateCaster.getEntityName(cfc)); 715 } 716 717 public Component getEntityByEntityName(String entityName,boolean unique) throws PageException { 718 Component cfc; 719 720 721 CFCInfo info = cfcs.get(entityName.toLowerCase()); 722 if(info!=null) { 723 cfc=info.getCFC(); 724 return unique?(Component)Duplicator.duplicate(cfc,false):cfc; 725 } 726 727 if(arr!=null){ 728 Iterator<Component> it2 = arr.iterator(); 729 while(it2.hasNext()){ 730 cfc=it2.next(); 731 if(HibernateCaster.getEntityName(cfc).equalsIgnoreCase(entityName)) 732 return unique?(Component)Duplicator.duplicate(cfc,false):cfc; 733 } 734 } 735 736 737 738 throw new ORMException(this,"entity ["+entityName+"] does not exist"); 739 740 } 741 742 743 744 public String[] getEntityNames() { 745 Iterator<Entry<String, CFCInfo>> it = cfcs.entrySet().iterator(); 746 String[] names=new String[cfcs.size()]; 747 int index=0; 748 while(it.hasNext()){ 749 names[index++]=HibernateCaster.getEntityName(it.next().getValue().getCFC()); 750 //names[index++]=it.next().getValue().getCFC().getName(); 751 } 752 return names; 753 754 //return cfcs.keySet().toArray(new String[cfcs.size()]); 755 } 756 757 public String convertTableName(String tableName) { 758 if(tableName==null) return null; 759 //print.o("table:"+namingStrategy.getType()+":"+tableName+":"+namingStrategy.convertTableName(tableName)); 760 return namingStrategy.convertTableName(tableName); 761 } 762 763 public String convertColumnName(String columnName) { 764 if(columnName==null) return null; 765 //print.o("column:"+namingStrategy.getType()+":"+columnName+":"+namingStrategy.convertTableName(columnName)); 766 return namingStrategy.convertColumnName(columnName); 767 } 768 769 770 771 } 772 class CFCInfo { 773 private String xml; 774 private long modified; 775 private Component cfc; 776 777 public CFCInfo(long modified, String xml, Component cfc) { 778 this.modified=modified; 779 this.xml=xml; 780 this.cfc=cfc; 781 } 782 /** 783 * @return the cfc 784 */ 785 public Component getCFC() { 786 return cfc; 787 } 788 /** 789 * @return the xml 790 */ 791 public String getXML() { 792 return xml; 793 } 794 /** 795 * @return the modified 796 */ 797 public long getModified() { 798 return modified; 799 } 800 801 } 802