KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > impl > SessionFactoryImpl


1 //$Id: SessionFactoryImpl.java,v 1.87 2005/07/21 01:11:51 oneovthafew Exp $
2
package org.hibernate.impl;
3
4 import java.io.IOException JavaDoc;
5 import java.io.InvalidObjectException JavaDoc;
6 import java.io.ObjectInputStream JavaDoc;
7 import java.io.ObjectOutputStream JavaDoc;
8 import java.io.ObjectStreamException JavaDoc;
9 import java.io.Serializable JavaDoc;
10 import java.sql.Connection JavaDoc;
11 import java.util.ArrayList JavaDoc;
12 import java.util.Collections JavaDoc;
13 import java.util.HashMap JavaDoc;
14 import java.util.Hashtable JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.Map JavaDoc;
17 import java.util.Properties JavaDoc;
18 import java.util.Set JavaDoc;
19 import java.util.HashSet JavaDoc;
20
21 import javax.naming.NamingException JavaDoc;
22 import javax.naming.Reference JavaDoc;
23 import javax.naming.StringRefAddr JavaDoc;
24 import javax.transaction.Synchronization JavaDoc;
25 import javax.transaction.Transaction JavaDoc;
26 import javax.transaction.TransactionManager JavaDoc;
27
28 import net.sf.cglib.core.KeyFactory;
29
30 import org.apache.commons.collections.ReferenceMap;
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33 import org.hibernate.AssertionFailure;
34 import org.hibernate.ConnectionReleaseMode;
35 import org.hibernate.EntityMode;
36 import org.hibernate.HibernateException;
37 import org.hibernate.Interceptor;
38 import org.hibernate.MappingException;
39 import org.hibernate.QueryException;
40 import org.hibernate.SessionFactory;
41 import org.hibernate.StatelessSession;
42 import org.hibernate.cache.Cache;
43 import org.hibernate.cache.CacheConcurrencyStrategy;
44 import org.hibernate.cache.CacheFactory;
45 import org.hibernate.cache.CacheKey;
46 import org.hibernate.cache.QueryCache;
47 import org.hibernate.cache.UpdateTimestampsCache;
48 import org.hibernate.cfg.Configuration;
49 import org.hibernate.cfg.Settings;
50 import org.hibernate.connection.ConnectionProvider;
51 import org.hibernate.dialect.Dialect;
52 import org.hibernate.engine.FilterDefinition;
53 import org.hibernate.engine.Mapping;
54 import org.hibernate.engine.NamedQueryDefinition;
55 import org.hibernate.engine.NamedSQLQueryDefinition;
56 import org.hibernate.engine.SessionFactoryImplementor;
57 import org.hibernate.engine.ResultSetMappingDefinition;
58 import org.hibernate.event.SessionEventListenerConfig;
59 import org.hibernate.exception.SQLExceptionConverter;
60 import org.hibernate.hql.FilterTranslator;
61 import org.hibernate.hql.QuerySplitter;
62 import org.hibernate.hql.QueryTranslator;
63 import org.hibernate.id.IdentifierGenerator;
64 import org.hibernate.id.UUIDHexGenerator;
65 import org.hibernate.jdbc.BatcherFactory;
66 import org.hibernate.mapping.Collection;
67 import org.hibernate.mapping.PersistentClass;
68 import org.hibernate.mapping.RootClass;
69 import org.hibernate.metadata.ClassMetadata;
70 import org.hibernate.metadata.CollectionMetadata;
71 import org.hibernate.persister.PersisterFactory;
72 import org.hibernate.persister.collection.CollectionPersister;
73 import org.hibernate.persister.entity.EntityPersister;
74 import org.hibernate.persister.entity.Queryable;
75 import org.hibernate.pretty.MessageHelper;
76 import org.hibernate.stat.Statistics;
77 import org.hibernate.stat.StatisticsImpl;
78 import org.hibernate.stat.StatisticsImplementor;
79 import org.hibernate.tool.hbm2ddl.SchemaExport;
80 import org.hibernate.tool.hbm2ddl.SchemaUpdate;
81 import org.hibernate.transaction.TransactionFactory;
82 import org.hibernate.type.Type;
83 import org.hibernate.type.AssociationType;
84 import org.hibernate.util.CollectionHelper;
85 import org.hibernate.util.JTAHelper;
86 import org.hibernate.util.ReflectHelper;
87
88
89 /**
90  * Concrete implementation of the <tt>SessionFactory</tt> interface. Has the following
91  * responsibilites
92  * <ul>
93  * <li>caches configuration settings (immutably)
94  * <li>caches "compiled" mappings ie. <tt>EntityPersister</tt>s and
95  * <tt>CollectionPersister</tt>s (immutable)
96  * <li>caches "compiled" queries (memory sensitive cache)
97  * <li>manages <tt>PreparedStatement</tt>s
98  * <li> delegates JDBC <tt>Connection</tt> management to the <tt>ConnectionProvider</tt>
99  * <li>factory for instances of <tt>SessionImpl</tt>
100  * </ul>
101  * This class must appear immutable to clients, even if it does all kinds of caching
102  * and pooling under the covers. It is crucial that the class is not only thread
103  * safe, but also highly concurrent. Synchronization must be used extremely sparingly.
104  *
105  * @see org.hibernate.connection.ConnectionProvider
106  * @see org.hibernate.classic.Session
107  * @see org.hibernate.hql.QueryTranslator
108  * @see org.hibernate.persister.entity.EntityPersister
109  * @see org.hibernate.persister.collection.CollectionPersister
110  * @author Gavin King
111  */

112 public final class SessionFactoryImpl implements SessionFactory, SessionFactoryImplementor {
113
114     private final String JavaDoc name;
115     private final String JavaDoc uuid;
116
117     private final transient Map JavaDoc entityPersisters;
118     private final transient Map JavaDoc classMetadata;
119     private final transient Map JavaDoc collectionPersisters;
120     private final transient Map JavaDoc collectionMetadata;
121     private final transient Map JavaDoc collectionRolesByEntityParticipant;
122     private final transient Map JavaDoc identifierGenerators;
123     private final transient Map JavaDoc namedQueries;
124     private final transient Map JavaDoc namedSqlQueries;
125     private final transient Map JavaDoc sqlResultSetMappings;
126     private final transient Map JavaDoc filters;
127     private final transient Map JavaDoc imports;
128     private final transient Interceptor interceptor;
129     private final transient Settings settings;
130     private final transient Properties JavaDoc properties;
131     private transient SchemaExport schemaExport;
132     private final transient TransactionManager JavaDoc transactionManager;
133     private final transient QueryCache queryCache;
134     private final transient UpdateTimestampsCache updateTimestampsCache;
135     private final transient Map JavaDoc queryCaches;
136     private final transient Map JavaDoc allCacheRegions = new HashMap JavaDoc();
137     private final transient StatisticsImpl statistics = new StatisticsImpl(this);
138     
139     private transient boolean isClosed = false;
140
141     private static final IdentifierGenerator UUID_GENERATOR = new UUIDHexGenerator();
142
143     private SessionEventListenerConfig sessionEventListenerConfig;
144
145     private transient Map JavaDoc currentSessionMap = new Hashtable JavaDoc();
146
147     private static final Log log = LogFactory.getLog(SessionFactoryImpl.class);
148
149     public SessionFactoryImpl(
150             Configuration cfg,
151             Mapping mapping,
152             Settings settings,
153             SessionEventListenerConfig listeners)
154     throws HibernateException {
155
156         log.info("building session factory");
157
158         this.properties = cfg.getProperties();
159         this.interceptor = cfg.getInterceptor();
160         this.settings = settings;
161         this.sessionEventListenerConfig = listeners;
162         this.filters = cfg.getFilterDefinitions();
163
164         if ( log.isDebugEnabled() ) {
165             log.debug("Session factory constructed with filter configurations : " + filters);
166         }
167
168         if ( log.isDebugEnabled() ) log.debug(
169             "instantiating session factory with properties: " + properties
170         );
171
172         // Caches
173
settings.getCacheProvider().start( properties );
174
175         //Generators:
176

177         identifierGenerators = new HashMap JavaDoc();
178         Iterator JavaDoc classes = cfg.getClassMappings();
179         while ( classes.hasNext() ) {
180             PersistentClass model = (PersistentClass) classes.next();
181             if ( !model.isInherited() ) {
182                 IdentifierGenerator generator = model.getIdentifier().createIdentifierGenerator(
183                         settings.getDialect(),
184                         settings.getDefaultCatalogName(),
185                         settings.getDefaultSchemaName(),
186                         (RootClass) model
187                 );
188                 identifierGenerators.put( model.getEntityName(), generator );
189             }
190         }
191         
192         //Persisters:
193

194         Map JavaDoc caches = new HashMap JavaDoc();
195         entityPersisters = new HashMap JavaDoc();
196         Map JavaDoc classMeta = new HashMap JavaDoc();
197         classes = cfg.getClassMappings();
198         while ( classes.hasNext() ) {
199             PersistentClass model = (PersistentClass) classes.next();
200             model.prepareTemporaryTables( mapping, settings.getDialect() );
201             String JavaDoc cacheRegion = model.getRootClass().getCacheRegionName();
202             CacheConcurrencyStrategy cache = (CacheConcurrencyStrategy) caches.get(cacheRegion);
203             if (cache==null) {
204                 cache = CacheFactory.createCache(
205                     model.getCacheConcurrencyStrategy(),
206                     cacheRegion,
207                     model.isMutable(),
208                     settings,
209                     properties
210                 );
211                 if (cache!=null) {
212                     caches.put(cacheRegion, cache);
213                     allCacheRegions.put( cache.getRegionName(), cache.getCache() );
214                 }
215             }
216             EntityPersister cp = PersisterFactory.createClassPersister(model, cache, this, mapping);
217             entityPersisters.put( model.getEntityName(), cp );
218             classMeta.put( model.getEntityName(), cp.getClassMetadata() );
219         }
220         classMetadata = Collections.unmodifiableMap(classMeta);
221
222         Map JavaDoc tmpEntityToCollectionRoleMap = new HashMap JavaDoc();
223         collectionPersisters = new HashMap JavaDoc();
224         Iterator JavaDoc collections = cfg.getCollectionMappings();
225         while ( collections.hasNext() ) {
226             Collection model = (Collection) collections.next();
227             CacheConcurrencyStrategy cache = CacheFactory.createCache(
228                 model.getCacheConcurrencyStrategy(),
229                 model.getCacheRegionName(),
230                 true,
231                 settings,
232                 properties
233             );
234             if (cache!=null) allCacheRegions.put( cache.getRegionName(), cache.getCache() );
235             CollectionPersister persister = PersisterFactory.createCollectionPersister(cfg, model, cache, this);
236             collectionPersisters.put( model.getRole(), persister.getCollectionMetadata() );
237             Type indexType = persister.getIndexType();
238             if ( indexType != null && indexType.isAssociationType() && !indexType.isAnyType() ) {
239                 String JavaDoc entityName = ( ( AssociationType ) indexType ).getAssociatedEntityName( this );
240                 Set JavaDoc roles = ( Set JavaDoc ) tmpEntityToCollectionRoleMap.get( entityName );
241                 if ( roles == null ) {
242                     roles = new HashSet JavaDoc();
243                     tmpEntityToCollectionRoleMap.put( entityName, roles );
244                 }
245                 roles.add( persister.getRole() );
246             }
247             Type elementType = persister.getElementType();
248             if ( elementType.isAssociationType() && !elementType.isAnyType() ) {
249                 String JavaDoc entityName = ( ( AssociationType ) elementType ).getAssociatedEntityName( this );
250                 Set JavaDoc roles = ( Set JavaDoc ) tmpEntityToCollectionRoleMap.get( entityName );
251                 if ( roles == null ) {
252                     roles = new HashSet JavaDoc();
253                     tmpEntityToCollectionRoleMap.put( entityName, roles );
254                 }
255                 roles.add( persister.getRole() );
256             }
257         }
258         collectionMetadata = Collections.unmodifiableMap(collectionPersisters);
259         Iterator JavaDoc itr = tmpEntityToCollectionRoleMap.entrySet().iterator();
260         while ( itr.hasNext() ) {
261             final Map.Entry JavaDoc entry = ( Map.Entry JavaDoc ) itr.next();
262             entry.setValue( Collections.unmodifiableSet( ( Set JavaDoc ) entry.getValue() ) );
263         }
264         collectionRolesByEntityParticipant = Collections.unmodifiableMap( tmpEntityToCollectionRoleMap );
265
266         //Named Queries:
267
// TODO: precompile and cache named queries
268
namedQueries = new HashMap JavaDoc( cfg.getNamedQueries() );
269         namedSqlQueries = new HashMap JavaDoc( cfg.getNamedSQLQueries() );
270         sqlResultSetMappings = new HashMap JavaDoc( cfg.getSqlResultSetMappings() );
271         imports = new HashMap JavaDoc( cfg.getImports() );
272
273         // after *all* persisters and named queries are registered
274
Iterator JavaDoc iter = entityPersisters.values().iterator();
275         while ( iter.hasNext() ) {
276             ( (EntityPersister) iter.next() ).postInstantiate();
277         }
278         iter = collectionPersisters.values().iterator();
279         while ( iter.hasNext() ) {
280             ( (CollectionPersister) iter.next() ).postInstantiate();
281         }
282
283         //JNDI + Serialization:
284

285         name = settings.getSessionFactoryName();
286         try {
287             uuid = (String JavaDoc) UUID_GENERATOR.generate(null, null);
288         }
289         catch (Exception JavaDoc e) {
290             throw new AssertionFailure("Could not generate UUID");
291         }
292         SessionFactoryObjectFactory.addInstance(uuid, name, this, properties);
293
294         log.debug("instantiated session factory");
295
296         if ( settings.isAutoCreateSchema() ) new SchemaExport(cfg, settings).create(false, true);
297         if ( settings.isAutoUpdateSchema() ) new SchemaUpdate(cfg, settings).execute(false, true);
298         if ( settings.isAutoDropSchema() ) schemaExport = new SchemaExport(cfg, settings);
299
300         if ( settings.getTransactionManagerLookup()!=null ) {
301             log.debug("obtaining JTA TransactionManager");
302             transactionManager = settings.getTransactionManagerLookup().getTransactionManager(properties);
303         }
304         else {
305             transactionManager = null;
306         }
307
308         if ( settings.isQueryCacheEnabled() ) {
309             updateTimestampsCache = new UpdateTimestampsCache(settings, properties);
310             queryCache = settings.getQueryCacheFactory()
311                     .getQueryCache(null, updateTimestampsCache, settings, properties);
312             queryCaches = new HashMap JavaDoc();
313             allCacheRegions.put( updateTimestampsCache.getRegionName(), updateTimestampsCache.getCache() );
314             allCacheRegions.put( queryCache.getRegionName(), queryCache.getCache() );
315         }
316         else {
317             updateTimestampsCache = null;
318             queryCache = null;
319             queryCaches = null;
320         }
321
322         //checking for named queries
323
Map JavaDoc errors = checkNamedQueries();
324         if ( !errors.isEmpty() ) {
325             Set JavaDoc keys = errors.keySet();
326             StringBuffer JavaDoc failingQueries = new StringBuffer JavaDoc("Errors in named queries: ");
327             for ( Iterator JavaDoc iterator = keys.iterator() ; iterator.hasNext() ; ) {
328                 String JavaDoc queryName = (String JavaDoc) iterator.next();
329                 HibernateException e = (HibernateException) errors.get(queryName);
330                 failingQueries.append(queryName);
331                 if ( iterator.hasNext() ) failingQueries.append(", ");
332                 log.error("Error in named query: " + queryName, e);
333             }
334             throw new HibernateException( failingQueries.toString() );
335         }
336         
337         //stats
338
getStatistics().setStatisticsEnabled( settings.isStatisticsEnabled() );
339     }
340
341     // Emulates constant time LRU/MRU algorithms for cache
342
// It is better to hold strong references on some (LRU/MRU) queries
343
private static final int MAX_STRONG_REF_COUNT = 128; //TODO: configurable?
344
private final transient Object JavaDoc[] strongRefs = new Object JavaDoc[MAX_STRONG_REF_COUNT]; //strong reference to MRU queries
345
private transient int strongRefIndex = 0;
346     private final transient Map JavaDoc softQueryCache = new ReferenceMap(ReferenceMap.SOFT, ReferenceMap.SOFT) ;
347     // both keys and values may be soft since value keeps a hard ref to the key (and there is a hard ref to MRU values)
348

349     //returns generated class instance
350
private static final QueryCacheKeyFactory QUERY_KEY_FACTORY;
351     private static final FilterCacheKeyFactory FILTER_KEY_FACTORY;
352     static {
353         QUERY_KEY_FACTORY = (QueryCacheKeyFactory) KeyFactory.create(QueryCacheKeyFactory.class);
354         FILTER_KEY_FACTORY = (FilterCacheKeyFactory) KeyFactory.create(FilterCacheKeyFactory.class);
355     }
356
357     static interface QueryCacheKeyFactory {
358         //Will not recalculate hashKey for constant queries
359
Object JavaDoc newInstance(String JavaDoc query, boolean scalar);
360     }
361
362     static interface FilterCacheKeyFactory {
363         //Will not recalculate hashKey for constant queries
364
Object JavaDoc newInstance(String JavaDoc role, String JavaDoc query, boolean scalar);
365     }
366
367     //TODO: this stuff can be implemented in separate class to reuse soft MRU/LRU caching
368
private synchronized Object JavaDoc get(Object JavaDoc key) {
369         Object JavaDoc result = softQueryCache.get(key);
370         if( result != null ) {
371             strongRefs[ ++strongRefIndex % MAX_STRONG_REF_COUNT ] = result;
372         }
373         return result;
374     }
375
376     private void put(Object JavaDoc key, Object JavaDoc value) {
377         softQueryCache.put(key, value);
378         strongRefs[ ++strongRefIndex % MAX_STRONG_REF_COUNT ] = value;
379     }
380
381     private synchronized QueryTranslator[] createQueryTranslators(
382             String JavaDoc[] concreteQueryStrings,
383             Object JavaDoc cacheKey,
384             Map JavaDoc enabledFilters
385     ) {
386         final int length = concreteQueryStrings.length;
387         final QueryTranslator[] queries = new QueryTranslator[length];
388         for ( int i=0; i<length; i++ ) {
389             queries[i] = settings.getQueryTranslatorFactory()
390                 .createQueryTranslator( concreteQueryStrings[i], enabledFilters, this );
391         }
392         if (cacheKey != null) put(cacheKey, queries);
393         return queries;
394     }
395
396     private synchronized FilterTranslator createFilterTranslator(
397             String JavaDoc filterString,
398             Object JavaDoc cacheKey,
399             Map JavaDoc enabledFilters
400     ) {
401         final FilterTranslator filter = settings.getQueryTranslatorFactory()
402             .createFilterTranslator(filterString, enabledFilters, this);
403         if (cacheKey != null) put(cacheKey, filter);
404         return filter;
405     }
406
407     private Map JavaDoc checkNamedQueries() throws HibernateException {
408         // Check named queries
409
Map JavaDoc errors = new HashMap JavaDoc();
410         Set JavaDoc names = namedQueries.keySet();
411         log.info("Checking " + namedQueries.size() + " named queries");
412         for ( Iterator JavaDoc iterator = names.iterator(); iterator.hasNext(); ) {
413             String JavaDoc queryName = (String JavaDoc) iterator.next();
414             NamedQueryDefinition q = (NamedQueryDefinition) namedQueries.get(queryName);
415
416             // this will throw an error if there's something wrong.
417
try {
418                 log.debug("Checking named query: " + queryName);
419                 //TODO: BUG! this currently fails for named queries for non-POJO entities
420
getQuery( q.getQueryString(), false, CollectionHelper.EMPTY_MAP );
421             }
422             catch (QueryException e) {
423                 errors.put(queryName, e);
424             }
425             catch (MappingException e) {
426                 errors.put(queryName, e);
427             }
428         }
429         
430         return errors;
431     }
432
433     public QueryTranslator[] getQuery(String JavaDoc queryString, boolean shallow, Map JavaDoc enabledFilters)
434     throws QueryException, MappingException {
435
436         // if there are no enabled filters, consider cached query compilations,
437
// otherwise generate/compile a new set of query translators
438
Object JavaDoc cacheKey = null;
439         QueryTranslator[] queries = null;
440         
441         if ( enabledFilters == null || enabledFilters.isEmpty() ) {
442             cacheKey = QUERY_KEY_FACTORY.newInstance(queryString, shallow);
443             queries = (QueryTranslator[]) get(cacheKey);
444         }
445
446         // have to be careful to ensure that if the JVM does out-of-order execution
447
// then another thread can't get an uncompiled QueryTranslator from the cache
448
// we also have to be very careful to ensure that other threads can perform
449
// compiled queries while another query is being compiled
450

451         if ( queries==null ) {
452             // a query that names an interface or unmapped class in the from clause
453
// is actually executed as multiple queries
454
String JavaDoc[] concreteQueryStrings = QuerySplitter.concreteQueries(queryString, this);
455             queries = createQueryTranslators(concreteQueryStrings, cacheKey, enabledFilters);
456         }
457         for ( int i=0; i<queries.length; i++) {
458 // queries[i].compile(this, settings.getQuerySubstitutions(), shallow, enabledFilters);
459
queries[i].compile( settings.getQuerySubstitutions(), shallow );
460         }
461         // see comment above. note that QueryTranslator.compile() is synchronized
462
return queries;
463
464     }
465
466     public FilterTranslator getFilter(
467             String JavaDoc filterString,
468             String JavaDoc collectionRole,
469             boolean scalar,
470             Map JavaDoc enabledFilters)
471     throws QueryException, MappingException {
472
473         Object JavaDoc cacheKey = null;
474         FilterTranslator filter = null;
475
476         if ( enabledFilters == null || enabledFilters.isEmpty() ) {
477             cacheKey = FILTER_KEY_FACTORY.newInstance(collectionRole, filterString, scalar);
478             filter = (FilterTranslator) get(cacheKey);
479         }
480
481         if ( filter==null ) {
482             filter = createFilterTranslator(filterString, cacheKey, enabledFilters);
483         }
484 // filter.compile(collectionRole, this, settings.getQuerySubstitutions(), scalar, enabledFilters);
485
filter.compile( collectionRole, settings.getQuerySubstitutions(), scalar );
486         // see comment above. note that FilterTranslator.compile() is synchronized
487
return filter;
488
489     }
490
491     public StatelessSession openStatelessSession() {
492         return new StatelessSessionImpl( null, this );
493     }
494     
495     public StatelessSession openStatelessSession(Connection JavaDoc connection) {
496         return new StatelessSessionImpl( connection, this );
497     }
498     
499     private SessionImpl openSession(
500         Connection JavaDoc connection,
501         boolean autoClose,
502         long timestamp,
503         Interceptor sessionLocalInterceptor
504     ) {
505         return new SessionImpl(
506                 connection,
507                 this,
508                 autoClose,
509                 timestamp,
510                 sessionLocalInterceptor,
511                 sessionEventListenerConfig,
512                 settings.getDefaultEntityMode(),
513                 settings.isFlushBeforeCompletionEnabled(),
514                 settings.isAutoCloseSessionEnabled(),
515                 settings.getConnectionReleaseMode()
516             );
517     }
518
519     public org.hibernate.classic.Session openSession(Connection JavaDoc connection, Interceptor sessionLocalInterceptor) {
520         return openSession(connection, false, Long.MIN_VALUE, sessionLocalInterceptor);
521     }
522
523     public org.hibernate.classic.Session openSession(Interceptor sessionLocalInterceptor)
524     throws HibernateException {
525         // note that this timestamp is not correct if the connection provider
526
// returns an older JDBC connection that was associated with a
527
// transaction that was already begun before openSession() was called
528
// (don't know any possible solution to this!)
529
long timestamp = settings.getCacheProvider().nextTimestamp();
530         return openSession( null, true, timestamp, sessionLocalInterceptor );
531     }
532
533     public org.hibernate.classic.Session openSession(Connection JavaDoc connection) {
534         return openSession(connection, interceptor); //prevents this session from adding things to cache
535
}
536
537     public org.hibernate.classic.Session openSession() throws HibernateException {
538         return openSession(interceptor);
539     }
540     
541     public org.hibernate.classic.Session openTemporarySession() throws HibernateException {
542         return new SessionImpl(
543                 null,
544                 this,
545                 true,
546                 settings.getCacheProvider().nextTimestamp(),
547                 interceptor,
548                 sessionEventListenerConfig,
549                 settings.getDefaultEntityMode(),
550                 false,
551                 false,
552                 ConnectionReleaseMode.AFTER_STATEMENT
553             );
554     }
555
556     public org.hibernate.classic.Session getCurrentSession() throws HibernateException {
557         if ( transactionManager == null ) {
558             throw new HibernateException( "No TransactionManagerLookup specified" );
559         }
560
561         Transaction JavaDoc txn = null;
562         try {
563             txn = transactionManager.getTransaction();
564             if ( txn == null ) {
565                 throw new HibernateException( "Unable to locate current JTA transaction" );
566             }
567             if ( !JTAHelper.isInProgress( txn.getStatus() ) ) {
568                 // We could register the session against the transaction even though it is
569
// not started, but we'd have no guarentee of ever getting the map
570
// entries cleaned up (aside from spawning threads).
571
throw new HibernateException( "Current transaction is not in progress" );
572             }
573         }
574         catch( HibernateException e ) {
575             throw e;
576         }
577         catch( Throwable JavaDoc t ) {
578             throw new HibernateException( "Problem locating/validating JTA transaction", t );
579         }
580
581         org.hibernate.classic.Session currentSession = (org.hibernate.classic.Session) currentSessionMap.get( txn );
582
583         if ( currentSession == null ) {
584             currentSession = new SessionImpl(
585                     null,
586                     this,
587                     true,
588                     settings.getCacheProvider().nextTimestamp(),
589                     interceptor,
590                     sessionEventListenerConfig,
591                     settings.getDefaultEntityMode(),
592                     true,
593                     true,
594                     ConnectionReleaseMode.AFTER_STATEMENT
595                 );
596             try {
597                 txn.registerSynchronization(
598                         new CurrentSessionCleanupSynch( txn, this )
599                     );
600             }
601             catch( Throwable JavaDoc t ) {
602                 try {
603                     currentSession.close();
604                 }
605                 catch( Throwable JavaDoc ignore ) {
606                     log.debug( "Unable to release generated current-session on failed synch registration", ignore );
607                 }
608                 throw new HibernateException( "Unable to register cleanup Synchronization with TransactionManager" );
609             }
610
611             currentSessionMap.put( txn, currentSession );
612         }
613
614         return currentSession;
615     }
616
617     public EntityPersister getEntityPersister(String JavaDoc entityName) throws MappingException {
618         EntityPersister result = (EntityPersister) entityPersisters.get(entityName);
619         if (result==null) {
620             throw new MappingException( "Unknown entity: " + entityName );
621         }
622         return result;
623     }
624
625     public CollectionPersister getCollectionPersister(String JavaDoc role) throws MappingException {
626         CollectionPersister result = (CollectionPersister) collectionPersisters.get(role);
627         if (result==null) {
628             throw new MappingException( "Unknown collection role: " + role );
629         }
630         return result;
631     }
632     
633     public Settings getSettings() {
634         return settings;
635     }
636
637     public Dialect getDialect() {
638         return settings.getDialect();
639     }
640
641     public TransactionFactory getTransactionFactory() {
642         return settings.getTransactionFactory();
643     }
644
645     public TransactionManager JavaDoc getTransactionManager() {
646         return transactionManager;
647     }
648
649     public SQLExceptionConverter getSQLExceptionConverter() {
650         return settings.getSQLExceptionConverter();
651     }
652
653     public Set JavaDoc getCollectionRolesByEntityParticipant(String JavaDoc entityName) {
654         return ( Set JavaDoc ) collectionRolesByEntityParticipant.get( entityName );
655     }
656
657     // from javax.naming.Referenceable
658
public Reference JavaDoc getReference() throws NamingException JavaDoc {
659         log.debug("Returning a Reference to the SessionFactory");
660         return new Reference JavaDoc(
661             SessionFactoryImpl.class.getName(),
662             new StringRefAddr JavaDoc("uuid", uuid),
663             SessionFactoryObjectFactory.class.getName(),
664             null
665         );
666     }
667
668     private Object JavaDoc readResolve() throws ObjectStreamException JavaDoc {
669         log.trace("Resolving serialized SessionFactory");
670         // look for the instance by uuid
671
Object JavaDoc result = SessionFactoryObjectFactory.getInstance(uuid);
672         if (result==null) {
673             // in case we were deserialized in a different JVM, look for an instance with the same name
674
// (alternatively we could do an actual JNDI lookup here....)
675
result = SessionFactoryObjectFactory.getNamedInstance(name);
676             if (result==null) {
677                 throw new InvalidObjectException JavaDoc("Could not find a SessionFactory named: " + name);
678             }
679             else {
680                 log.debug("resolved SessionFactory by name");
681             }
682         }
683         else {
684             log.debug("resolved SessionFactory by uid");
685         }
686         return result;
687     }
688
689     public NamedQueryDefinition getNamedQuery(String JavaDoc queryName) {
690         return (NamedQueryDefinition) namedQueries.get(queryName);
691     }
692
693     public NamedSQLQueryDefinition getNamedSQLQuery(String JavaDoc queryName) {
694         return (NamedSQLQueryDefinition) namedSqlQueries.get(queryName);
695     }
696
697     public ResultSetMappingDefinition getResultSetMapping(String JavaDoc resultSetName) {
698         return (ResultSetMappingDefinition) sqlResultSetMappings.get(resultSetName);
699     }
700
701     public Type getIdentifierType(String JavaDoc className) throws MappingException {
702         return getEntityPersister(className).getIdentifierType();
703     }
704     public String JavaDoc getIdentifierPropertyName(String JavaDoc className) throws MappingException {
705         return getEntityPersister(className).getIdentifierPropertyName();
706     }
707
708     private final void readObject(ObjectInputStream JavaDoc in) throws IOException JavaDoc, ClassNotFoundException JavaDoc {
709         log.trace("deserializing");
710         in.defaultReadObject();
711         log.debug("deserialized: " + uuid);
712     }
713     private final void writeObject(ObjectOutputStream JavaDoc out) throws IOException JavaDoc {
714         log.debug("serializing: " + uuid);
715         out.defaultWriteObject();
716         log.trace("serialized");
717     }
718
719     public Type[] getReturnTypes(String JavaDoc queryString) throws HibernateException {
720         return getRepresentativeQuery(queryString).getReturnTypes();
721     }
722
723     public String JavaDoc[] getReturnAliases(String JavaDoc queryString) throws HibernateException {
724         return getRepresentativeQuery(queryString).getReturnAliases();
725     }
726     
727     private QueryTranslator getRepresentativeQuery(String JavaDoc queryString) throws HibernateException {
728         String JavaDoc[] queries = QuerySplitter.concreteQueries(queryString, this);
729         if ( queries.length==0 ) throw new HibernateException("Query does not refer to any persistent classes: " + queryString);
730         return getQuery( queries[0], true, CollectionHelper.EMPTY_MAP )[0];
731     }
732
733     public ClassMetadata getClassMetadata(Class JavaDoc persistentClass) throws HibernateException {
734         return getClassMetadata( persistentClass.getName() );
735     }
736
737     public CollectionMetadata getCollectionMetadata(String JavaDoc roleName) throws HibernateException {
738         return (CollectionMetadata) collectionMetadata.get(roleName);
739     }
740
741     public ClassMetadata getClassMetadata(String JavaDoc entityName) throws HibernateException {
742         return (ClassMetadata) classMetadata.get(entityName);
743     }
744
745     /**
746      * Return the names of all persistent (mapped) classes that extend or implement the
747      * given class or interface, accounting for implicit/explicit polymorphism settings
748      * and excluding mapped subclasses/joined-subclasses of other classes in the result.
749      */

750     public String JavaDoc[] getImplementors(String JavaDoc className) throws MappingException {
751
752         final Class JavaDoc clazz;
753         try {
754             clazz = ReflectHelper.classForName(className);
755         }
756         catch (ClassNotFoundException JavaDoc cnfe) {
757             return new String JavaDoc[] { className }; //for a dynamic-class
758
}
759
760         ArrayList JavaDoc results = new ArrayList JavaDoc();
761         Iterator JavaDoc iter = entityPersisters.values().iterator();
762         while ( iter.hasNext() ) {
763             //test this entity to see if we must query it
764
EntityPersister testPersister = (EntityPersister) iter.next();
765             if ( testPersister instanceof Queryable ) {
766                 Queryable testQueryable = (Queryable) testPersister;
767                 String JavaDoc testClassName = testQueryable.getEntityName();
768                 boolean isMappedClass = className.equals(testClassName);
769                 if ( testQueryable.isExplicitPolymorphism() ) {
770                     if (isMappedClass) return new String JavaDoc[] { className }; //NOTE EARLY EXIT
771
}
772                 else {
773                     if (isMappedClass) {
774                         results.add(testClassName);
775                     }
776                     else {
777                         final Class JavaDoc mappedClass = testQueryable.getMappedClass( EntityMode.POJO );
778                         if ( mappedClass!=null && clazz.isAssignableFrom( mappedClass ) ) {
779                             final boolean assignableSuperclass;
780                             if ( testQueryable.isInherited() ) {
781                                 Class JavaDoc mappedSuperclass = getEntityPersister( testQueryable.getMappedSuperclass() ).getMappedClass( EntityMode.POJO);
782                                 assignableSuperclass = clazz.isAssignableFrom(mappedSuperclass);
783                             }
784                             else {
785                                 assignableSuperclass = false;
786                             }
787                             if (!assignableSuperclass) results.add(testClassName);
788                         }
789                     }
790                 }
791             }
792         }
793         return (String JavaDoc[]) results.toArray( new String JavaDoc[ results.size() ] );
794     }
795
796     public String JavaDoc getImportedClassName(String JavaDoc className) {
797         String JavaDoc result = (String JavaDoc) imports.get(className);
798         if (result==null) {
799             try {
800                 ReflectHelper.classForName(className);
801                 return className;
802             }
803             catch (ClassNotFoundException JavaDoc cnfe) {
804                 return null;
805             }
806         }
807         else {
808             return result;
809         }
810     }
811
812     public Map JavaDoc getAllClassMetadata() throws HibernateException {
813         return classMetadata;
814     }
815
816     public Map JavaDoc getAllCollectionMetadata() throws HibernateException {
817         return collectionMetadata;
818     }
819
820     /**
821      * Closes the session factory, releasing all held resources.
822      *
823      * <ol>
824      * <li>cleans up used cache regions and "stops" the cache provider.
825      * <li>close the JDBC connection
826      * <li>remove the JNDI binding
827      * </ol>
828      */

829     public void close() throws HibernateException {
830
831         log.info("closing");
832         
833         isClosed = true;
834
835         Iterator JavaDoc iter = entityPersisters.values().iterator();
836         while ( iter.hasNext() ) {
837             EntityPersister p = (EntityPersister) iter.next();
838             if ( p.hasCache() ) p.getCache().destroy();
839         }
840
841         iter = collectionPersisters.values().iterator();
842         while ( iter.hasNext() ) {
843             CollectionPersister p = (CollectionPersister) iter.next();
844             if ( p.hasCache() ) p.getCache().destroy();
845         }
846
847         if ( settings.isQueryCacheEnabled() ) {
848             queryCache.destroy();
849
850             iter = queryCaches.values().iterator();
851             while ( iter.hasNext() ) {
852                 QueryCache cache = (QueryCache) iter.next();
853                 cache.destroy();
854             }
855             updateTimestampsCache.destroy();
856         }
857
858         settings.getCacheProvider().stop();
859
860         try {
861             settings.getConnectionProvider().close();
862         }
863         finally {
864             SessionFactoryObjectFactory.removeInstance(uuid, name, properties);
865         }
866
867         if ( settings.isAutoDropSchema() ) schemaExport.drop(false, true);
868
869     }
870
871     public void evictEntity(String JavaDoc entityName, Serializable JavaDoc id) throws HibernateException {
872         EntityPersister p = getEntityPersister(entityName);
873         if ( p.hasCache() ) {
874             if ( log.isDebugEnabled() ) {
875                 log.debug( "evicting second-level cache: " + MessageHelper.infoString(p, id, this) );
876             }
877             CacheKey cacheKey = new CacheKey( id, p.getIdentifierType(), p.getRootEntityName(), EntityMode.POJO, this );
878             p.getCache().remove( cacheKey );
879         }
880     }
881
882     public void evictEntity(String JavaDoc entityName) throws HibernateException {
883         EntityPersister p = getEntityPersister(entityName);
884         if ( p.hasCache() ) {
885             if ( log.isDebugEnabled() ) {
886                 log.debug( "evicting second-level cache: " + p.getEntityName() );
887             }
888             p.getCache().clear();
889         }
890     }
891
892     public void evict(Class JavaDoc persistentClass, Serializable JavaDoc id) throws HibernateException {
893         EntityPersister p = getEntityPersister( persistentClass.getName() );
894         if ( p.hasCache() ) {
895             if ( log.isDebugEnabled() ) {
896                 log.debug( "evicting second-level cache: " + MessageHelper.infoString(p, id, this) );
897             }
898             CacheKey cacheKey = new CacheKey( id, p.getIdentifierType(), p.getRootEntityName(), EntityMode.POJO, this );
899             p.getCache().remove( cacheKey );
900         }
901     }
902
903     public void evict(Class JavaDoc persistentClass) throws HibernateException {
904         EntityPersister p = getEntityPersister( persistentClass.getName() );
905         if ( p.hasCache() ) {
906             if ( log.isDebugEnabled() ) {
907                 log.debug( "evicting second-level cache: " + p.getEntityName() );
908             }
909             p.getCache().clear();
910         }
911     }
912
913     public void evictCollection(String JavaDoc roleName, Serializable JavaDoc id) throws HibernateException {
914         CollectionPersister p = getCollectionPersister(roleName);
915         if ( p.hasCache() ) {
916             if ( log.isDebugEnabled() ) {
917                 log.debug( "evicting second-level cache: " + MessageHelper.collectionInfoString(p, id, this) );
918             }
919             CacheKey cacheKey = new CacheKey( id, p.getKeyType(), p.getRole(), EntityMode.POJO, this );
920             p.getCache().remove( cacheKey );
921         }
922     }
923
924     public void evictCollection(String JavaDoc roleName) throws HibernateException {
925         CollectionPersister p = getCollectionPersister(roleName);
926         if ( p.hasCache() ) {
927             if ( log.isDebugEnabled() ) log.debug( "evicting second-level cache: " + p.getRole() );
928             p.getCache().clear();
929         }
930     }
931
932     public Type getReferencedPropertyType(String JavaDoc className, String JavaDoc propertyName)
933         throws MappingException {
934         return getEntityPersister(className).getPropertyType(propertyName);
935     }
936
937     public ConnectionProvider getConnectionProvider() {
938         return settings.getConnectionProvider();
939     }
940
941     public UpdateTimestampsCache getUpdateTimestampsCache() {
942         return updateTimestampsCache;
943     }
944     
945     public QueryCache getQueryCache() {
946         return queryCache;
947     }
948
949     public QueryCache getQueryCache(String JavaDoc cacheRegion) throws HibernateException {
950         if (cacheRegion==null) {
951             return getQueryCache();
952         }
953         
954         if ( !settings.isQueryCacheEnabled() ) {
955             return null;
956         }
957
958         synchronized (allCacheRegions) {
959             QueryCache currentQueryCache = (QueryCache) queryCaches.get(cacheRegion);
960             if (currentQueryCache==null) {
961                 currentQueryCache = settings.getQueryCacheFactory()
962                     .getQueryCache(cacheRegion, updateTimestampsCache, settings, properties);
963                 queryCaches.put(cacheRegion, currentQueryCache);
964                 allCacheRegions.put( currentQueryCache.getRegionName(), currentQueryCache.getCache() );
965             }
966             return currentQueryCache;
967         }
968     }
969     
970     public Cache getSecondLevelCacheRegion(String JavaDoc regionName) {
971         synchronized (allCacheRegions) {
972             return (Cache) allCacheRegions.get(regionName);
973         }
974     }
975     
976     public Map JavaDoc getAllSecondLevelCacheRegions() {
977         synchronized (allCacheRegions) {
978             return new HashMap JavaDoc(allCacheRegions);
979         }
980     }
981     
982     public boolean isClosed() {
983         return isClosed;
984     }
985
986     public Statistics getStatistics() {
987         return statistics;
988     }
989     
990     public StatisticsImplementor getStatisticsImplementor() {
991         return statistics;
992     }
993     
994     public void evictQueries() throws HibernateException {
995         if ( settings.isQueryCacheEnabled() ) {
996             queryCache.clear();
997         }
998     }
999
1000    public void evictQueries(String JavaDoc cacheRegion) throws HibernateException {
1001        if (cacheRegion==null) {
1002            throw new NullPointerException JavaDoc("use the zero-argument form to evict the default query cache");
1003        }
1004        else {
1005            synchronized (allCacheRegions) {
1006                if ( settings.isQueryCacheEnabled() ) {
1007                    QueryCache currentQueryCache = (QueryCache) queryCaches.get(cacheRegion);
1008                    if (currentQueryCache!=null) currentQueryCache.clear();
1009                }
1010            }
1011        }
1012    }
1013
1014    public FilterDefinition getFilterDefinition(String JavaDoc filterName) throws IllegalArgumentException JavaDoc {
1015        FilterDefinition def = (FilterDefinition) filters.get(filterName);
1016        if (def == null) {
1017            // TODO: what should be the actual type thrown?
1018
throw new IllegalArgumentException JavaDoc("No such filter configured [" + filterName + "]");
1019        }
1020        return def;
1021    }
1022
1023    public BatcherFactory getBatcherFactory() {
1024        return settings.getBatcherFactory();
1025    }
1026    
1027    public IdentifierGenerator getIdentifierGenerator(String JavaDoc rootEntityName) {
1028        return (IdentifierGenerator) identifierGenerators.get(rootEntityName);
1029    }
1030
1031    static class CurrentSessionCleanupSynch implements Synchronization JavaDoc {
1032        private Transaction JavaDoc txn;
1033        private SessionFactoryImpl impl;
1034
1035        public CurrentSessionCleanupSynch(Transaction JavaDoc txn, SessionFactoryImpl impl) {
1036            this.txn = txn;
1037            this.impl = impl;
1038        }
1039
1040        public void beforeCompletion() {
1041        }
1042
1043        public void afterCompletion(int i) {
1044            impl.currentSessionMap.remove( txn );
1045        }
1046    }
1047}
1048
Popular Tags