001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.orm.hibernate; 020 021import java.io.IOException; 022import java.sql.SQLException; 023import java.util.ArrayList; 024import java.util.HashMap; 025import java.util.Iterator; 026import java.util.List; 027import java.util.Map; 028 029import lucee.commons.io.log.Log; 030import lucee.loader.util.Util; 031import lucee.runtime.Component; 032import lucee.runtime.PageContext; 033import lucee.runtime.db.DataSource; 034import lucee.runtime.db.DatasourceConnection; 035import lucee.runtime.exp.PageException; 036import lucee.runtime.orm.ORMConfiguration; 037import lucee.runtime.orm.ORMSession; 038import lucee.runtime.orm.hibernate.naming.CFCNamingStrategy; 039import lucee.runtime.orm.hibernate.naming.DefaultNamingStrategy; 040import lucee.runtime.orm.hibernate.naming.SmartNamingStrategy; 041import lucee.runtime.orm.naming.NamingStrategy; 042import lucee.runtime.type.Collection; 043import lucee.runtime.type.Collection.Key; 044import lucee.runtime.type.KeyImpl; 045import lucee.runtime.type.Struct; 046import lucee.runtime.type.util.ListUtil; 047 048import org.hibernate.SessionFactory; 049import org.hibernate.cfg.Configuration; 050import org.hibernate.engine.SessionFactoryImplementor; 051import org.hibernate.engine.query.QueryPlanCache; 052 053public class SessionFactoryData { 054 055 public List<Component> tmpList; 056 057 private final Map<Key,DataSource> sources=new HashMap<Key, DataSource>(); 058 private final Map<Key,Map<String, CFCInfo>> cfcs=new HashMap<Key, Map<String,CFCInfo>>(); 059 private final Map<Key,Configuration> configurations=new HashMap<Key,Configuration>(); 060 private final Map<Key,SessionFactory> factories=new HashMap<Key,SessionFactory>(); 061 private final Map<Key,QueryPlanCache> queryPlanCaches=new HashMap<Key,QueryPlanCache>(); 062 063 private final ORMConfiguration ormConf; 064 private NamingStrategy namingStrategy; 065 private final HibernateORMEngine engine; 066 private Struct tableInfo=CommonUtil.createStruct(); 067 private String cfcNamingStrategy; 068 069 070 071 public SessionFactoryData(HibernateORMEngine engine,ORMConfiguration ormConf) { 072 this.engine=engine; 073 this.ormConf=ormConf; 074 } 075 076 public ORMConfiguration getORMConfiguration(){ 077 return ormConf; 078 } 079 public HibernateORMEngine getEngine(){ 080 return engine; 081 } 082 083 public QueryPlanCache getQueryPlanCache(Key datasSourceName) { 084 QueryPlanCache qpc = queryPlanCaches.get(datasSourceName); 085 if(qpc==null){ 086 queryPlanCaches.put(datasSourceName, qpc=new QueryPlanCache((SessionFactoryImplementor) getFactory(datasSourceName))); 087 } 088 return qpc; 089 } 090 091 092 public NamingStrategy getNamingStrategy() throws PageException { 093 if(namingStrategy==null) { 094 String strNamingStrategy=ormConf.namingStrategy(); 095 if(Util.isEmpty(strNamingStrategy,true)) { 096 namingStrategy=DefaultNamingStrategy.INSTANCE; 097 } 098 else { 099 strNamingStrategy=strNamingStrategy.trim(); 100 if("default".equalsIgnoreCase(strNamingStrategy)) 101 namingStrategy=DefaultNamingStrategy.INSTANCE; 102 else if("smart".equalsIgnoreCase(strNamingStrategy)) 103 namingStrategy=SmartNamingStrategy.INSTANCE; 104 else { 105 CFCNamingStrategy cfcNS = new CFCNamingStrategy(cfcNamingStrategy==null?strNamingStrategy:cfcNamingStrategy); 106 cfcNamingStrategy=cfcNS.getComponent().getPageSource().getComponentName(); 107 namingStrategy=cfcNS; 108 109 } 110 } 111 } 112 if(namingStrategy==null) return DefaultNamingStrategy.INSTANCE; 113 return namingStrategy; 114 } 115 116 117 public CFCInfo checkExistent(PageContext pc,Component cfc) throws PageException { 118 CFCInfo info = getCFC(HibernateCaster.getEntityName(cfc), null); 119 if(info!=null) return info; 120 121 throw ExceptionUtil.createException(this,null,"there is no mapping definition for component ["+cfc.getAbsName()+"]",""); 122 } 123 124 public List<String> getEntityNames() { 125 Iterator<Map<String, CFCInfo>> it = cfcs.values().iterator(); 126 List<String> names=new ArrayList<String>(); 127 Iterator<CFCInfo> _it; 128 while(it.hasNext()){ 129 _it = it.next().values().iterator(); 130 while(_it.hasNext()){ 131 names.add(HibernateCaster.getEntityName(_it.next().getCFC())); 132 } 133 } 134 return names; 135 } 136 137 public Component getEntityByEntityName(String entityName,boolean unique) throws PageException { 138 Component cfc; 139 140 // first check cfcs for this entity 141 CFCInfo info = getCFC(entityName,null); 142 if(info!=null) { 143 cfc=info.getCFC(); 144 return unique?(Component)cfc.duplicate(false):cfc; 145 } 146 147 // if parsing is in progress, the cfc can be found here 148 if(tmpList!=null){ 149 Iterator<Component> it = tmpList.iterator(); 150 while(it.hasNext()){ 151 cfc=it.next(); 152 if(HibernateCaster.getEntityName(cfc).equalsIgnoreCase(entityName)) 153 return unique?(Component)cfc.duplicate(false):cfc; 154 } 155 } 156 throw ExceptionUtil.createException((ORMSession)null,null,"entity ["+entityName+"] does not exist",""); 157 } 158 159 160 161 public Component getEntityByCFCName(String cfcName,boolean unique) throws PageException { 162 String name=cfcName; 163 int pointIndex=cfcName.lastIndexOf('.'); 164 if(pointIndex!=-1) { 165 name=cfcName.substring(pointIndex+1); 166 } 167 else 168 cfcName=null; 169 170 171 172 Component cfc; 173 List<String> names=new ArrayList<String>(); 174 175 List<Component> list = tmpList; 176 if(list!=null){ 177 int index=0; 178 Iterator<Component> it2 = list.iterator(); 179 while(it2.hasNext()){ 180 cfc=it2.next(); 181 names.add(cfc.getName()); 182 if(HibernateUtil.isEntity(ormConf,cfc,cfcName,name)) //if(cfc.equalTo(name)) 183 return unique?(Component)cfc.duplicate(false):cfc; 184 } 185 } 186 else { 187 // search cfcs 188 Iterator<Map<String, CFCInfo>> it = cfcs.values().iterator(); 189 Map<String, CFCInfo> _cfcs; 190 while(it.hasNext()){ 191 _cfcs = it.next(); 192 Iterator<CFCInfo> _it = _cfcs.values().iterator(); 193 while(_it.hasNext()){ 194 cfc=_it.next().getCFC(); 195 names.add(cfc.getName()); 196 if(HibernateUtil.isEntity(ormConf,cfc,cfcName,name)) //if(cfc.instanceOf(name)) 197 return unique?(Component)cfc.duplicate(false):cfc; 198 } 199 } 200 } 201 202 CFCInfo info = getCFC(name,null); 203 if(info!=null) { 204 cfc=info.getCFC(); 205 return unique?(Component)cfc.duplicate(false):cfc; 206 } 207 208 throw ExceptionUtil.createException((ORMSession)null,null,"entity ["+name+"] "+(Util.isEmpty(cfcName)?"":"with cfc name ["+cfcName+"] ")+"does not exist, existing entities are ["+ListUtil.listToList(names, ", ")+"]",""); 209 210 } 211 212 // Datasource specific 213 public Configuration getConfiguration(DataSource ds){ 214 return configurations.get(KeyImpl.init(ds.getName())); 215 } 216 public Configuration getConfiguration(Key key){ 217 return configurations.get(key); 218 } 219 220 public void setConfiguration(Log log,String mappings, DatasourceConnection dc) throws PageException, SQLException, IOException { 221 configurations.put(KeyImpl.init(dc.getDatasource().getName()),HibernateSessionFactory.createConfiguration(log,mappings,dc,this)); 222 } 223 224 225 public void buildSessionFactory(Key datasSourceName) { 226 //Key key=KeyImpl.init(ds.getName()); 227 Configuration conf = getConfiguration(datasSourceName); 228 if(conf==null) throw new RuntimeException("cannot build factory because there is no configuration"); // this should never happen 229 factories.put(datasSourceName, conf.buildSessionFactory()); 230 } 231 232 public SessionFactory getFactory(Key datasSourceName){ 233 SessionFactory factory = factories.get(datasSourceName); 234 if(factory==null && getConfiguration(datasSourceName)!=null) buildSessionFactory(datasSourceName);// this should never be happen 235 return factory; 236 } 237 238 239 public void reset() { 240 configurations.clear(); 241 Iterator<SessionFactory> it = factories.values().iterator(); 242 while(it.hasNext()){ 243 it.next().close(); 244 } 245 factories.clear(); 246 //namingStrategy=null; because the ormconf not change, this has not to change as well 247 tableInfo=CommonUtil.createStruct(); 248 } 249 250 251 public Struct getTableInfo(DatasourceConnection dc, String tableName) throws PageException { 252 Collection.Key keyTableName=CommonUtil.createKey(tableName); 253 Struct columnsInfo = (Struct) tableInfo.get(keyTableName,null); 254 if(columnsInfo!=null) return columnsInfo; 255 256 columnsInfo = HibernateUtil.checkTable(dc,tableName,this); 257 tableInfo.setEL(keyTableName,columnsInfo); 258 return columnsInfo; 259 } 260 261 262 // CFC methods 263 public void addCFC(String entityName, CFCInfo info) { 264 DataSource ds = info.getDataSource(); 265 Key dsn=KeyImpl.init(ds.getName()); 266 267 Map<String, CFCInfo> map = cfcs.get(dsn); 268 if(map==null) cfcs.put(dsn, map=new HashMap<String, CFCInfo>()); 269 map.put(HibernateUtil.id(entityName), info); 270 sources.put(dsn, ds); 271 } 272 273 274 CFCInfo getCFC(String entityName, CFCInfo defaultValue) { 275 Iterator<Map<String, CFCInfo>> it = cfcs.values().iterator(); 276 while(it.hasNext()){ 277 CFCInfo info = it.next().get(HibernateUtil.id(entityName)); 278 if(info!=null) return info; 279 } 280 return defaultValue; 281 } 282 283 public Map<Key, Map<String, CFCInfo>> getCFCs() { 284 return cfcs; 285 } 286 287 /*public Map<String, CFCInfo> getCFCs(DataSource ds) { 288 Key key=KeyImpl.init(ds.getName()); 289 Map<String, CFCInfo> rtn = cfcs.get(key); 290 if(rtn==null) return new HashMap<String, CFCInfo>(); 291 return rtn; 292 }*/ 293 294 public Map<String, CFCInfo> getCFCs(Key datasSourceName) { 295 Map<String, CFCInfo> rtn = cfcs.get(datasSourceName); 296 if(rtn==null) return new HashMap<String, CFCInfo>(); 297 return rtn; 298 } 299 300 public void clearCFCs() { 301 cfcs.clear(); 302 } 303 304 public int sizeCFCs() { 305 Iterator<Map<String, CFCInfo>> it = cfcs.values().iterator(); 306 int size=0; 307 while(it.hasNext()){ 308 size+=it.next().size(); 309 } 310 return size; 311 } 312 313 public DataSource[] getDataSources() { 314 return sources.values().toArray(new DataSource[sources.size()]); 315 } 316 317 public void init() { 318 Iterator<Key> it = cfcs.keySet().iterator(); 319 while(it.hasNext()){ 320 getFactory(it.next()); 321 } 322 } 323 324 public Map<Key, SessionFactory> getFactories() { 325 Iterator<Key> it = cfcs.keySet().iterator(); 326 Map<Key,SessionFactory> map=new HashMap<Key, SessionFactory>(); 327 Key key; 328 while(it.hasNext()){ 329 key = it.next(); 330 map.put(key, getFactory(key)); 331 } 332 return map; 333 } 334 335 public DataSource getDataSource(Key datasSourceName) { 336 return sources.get(datasSourceName); 337 } 338}