1 //$Id: Ejb3Configuration.java 11218 2007-02-19 19:36:40Z epbernard $
2 package org.hibernate.ejb;
3
4 import java.io.BufferedInputStream;
5 import java.io.ByteArrayOutputStream;
6 import java.io.DataInputStream;
7 import java.io.File;
8 import java.io.IOException;
9 import java.io.InputStream;
10 import java.io.ObjectOutput;
11 import java.io.ObjectOutputStream;
12 import java.io.Serializable;
13 import java.net.URL;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.Enumeration;
18 import java.util.HashMap;
19 import java.util.Iterator;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Properties;
23 import java.util.Set;
24 import java.util.StringTokenizer;
25 import javax.naming.BinaryRefAddr;
26 import javax.naming.NamingException;
27 import javax.naming.Reference;
28 import javax.naming.Referenceable;
29 import javax.persistence.Embeddable;
30 import javax.persistence.Entity;
31 import javax.persistence.EntityManagerFactory;
32 import javax.persistence.EntityNotFoundException;
33 import javax.persistence.MappedSuperclass;
34 import javax.persistence.PersistenceException;
35 import javax.persistence.spi.PersistenceUnitInfo;
36 import javax.persistence.spi.PersistenceUnitTransactionType;
37 import javax.sql.DataSource;
38
39 import javassist.bytecode.AnnotationsAttribute;
40 import javassist.bytecode.ClassFile;
41 import org.apache.commons.logging.Log;
42 import org.apache.commons.logging.LogFactory;
43 import org.dom4j.DocumentException;
44 import org.dom4j.Element;
45 import org.dom4j.io.SAXReader;
46 import org.hibernate.HibernateException;
47 import org.hibernate.Interceptor;
48 import org.hibernate.MappingException;
49 import org.hibernate.MappingNotFoundException;
50 import org.hibernate.SessionFactory;
51 import org.hibernate.cfg.AnnotationConfiguration;
52 import org.hibernate.cfg.Configuration;
53 import org.hibernate.cfg.Environment;
54 import org.hibernate.cfg.NamingStrategy;
55 import org.hibernate.cfg.Settings;
56 import org.hibernate.cfg.SettingsFactory;
57 import org.hibernate.ejb.connection.InjectedDataSourceConnectionProvider;
58 import org.hibernate.ejb.instrument.InterceptFieldClassFileTransformer;
59 import org.hibernate.ejb.packaging.JarVisitor;
60 import org.hibernate.ejb.packaging.PersistenceMetadata;
61 import org.hibernate.ejb.packaging.PersistenceXmlLoader;
62 import org.hibernate.ejb.packaging.NamedInputStream;
63 import org.hibernate.ejb.transaction.JoinableCMTTransactionFactory;
64 import org.hibernate.ejb.util.ConfigurationHelper;
65 import org.hibernate.ejb.util.LogHelper;
66 import org.hibernate.ejb.util.NamingHelper;
67 import org.hibernate.engine.FilterDefinition;
68 import org.hibernate.event.EventListeners;
69 import org.hibernate.mapping.AuxiliaryDatabaseObject;
70 import org.hibernate.mapping.PersistentClass;
71 import org.hibernate.proxy.EntityNotFoundDelegate;
72 import org.hibernate.cfg.annotations.reflection.XMLContext;
73 import org.hibernate.secure.JACCConfiguration;
74 import org.hibernate.transaction.JDBCTransactionFactory;
75 import org.hibernate.util.CollectionHelper;
76 import org.hibernate.util.ReflectHelper;
77 import org.hibernate.util.StringHelper;
78 import org.hibernate.util.XMLHelper;
79 import org.jboss.util.file.ArchiveBrowser;
80 import org.xml.sax.EntityResolver;
81 import org.xml.sax.SAXException;
82
83 /**
84 * Allow a fine tuned configuration of an EJB 3.0 EntityManagerFactory
85 *
86 * A Ejb3Configuration object is only guaranteed to create one EntityManagerFactory.
87 * Multiple usage of #buildEntityManagerFactory() is not guaranteed.
88 *
89 * After #buildEntityManagerFactory() has been called, you no longer can change the configuration
90 * state (no class adding, no property change etc)
91 *
92 * When serialized / deserialized or retrieved from the JNDI, you no longer can change the
93 * configuration state (no class adding, no property change etc)
94 *
95 * Putting the configuration in the JNDI is an expensive operation that requires a partial
96 * serialization
97 *
98 * @author Emmanuel Bernard
99 */
100 public class Ejb3Configuration implements Serializable, Referenceable {
101 private static final String IMPLEMENTATION_NAME = HibernatePersistence.class.getName();
102 private static final String META_INF_ORM_XML = "META-INF/orm.xml";
103 private static Log log = LogFactory.getLog( Ejb3Configuration.class );
104 private static EntityNotFoundDelegate ejb3EntityNotFoundDelegate = new Ejb3EntityNotFoundDelegate();
105 private static Configuration DEFAULT_CONFIGURATION = new AnnotationConfiguration();
106
107 private static class Ejb3EntityNotFoundDelegate implements EntityNotFoundDelegate, Serializable {
108 public void handleEntityNotFound(String entityName, Serializable id) {
109 throw new EntityNotFoundException("Unable to find " + entityName + " with id " + id);
110 }
111 }
112
113 static {
114 Version.touch();
115 }
116
117 private AnnotationConfiguration cfg;
118 private SettingsFactory settingsFactory;
119 //made transient and not restored in deserialization on purpose, should no longer be called after restoration
120 private transient EventListenerConfigurator listenerConfigurator;
121 private PersistenceUnitTransactionType transactionType;
122 private boolean discardOnClose;
123 //made transient and not restored in deserialization on purpose, should no longer be called after restoration
124 private transient ClassLoader overridenClassLoader;
125 private boolean isConfigurationProcessed = false;
126
127
128 public Ejb3Configuration() {
129 settingsFactory = new InjectionSettingsFactory();
130 cfg = new AnnotationConfiguration( settingsFactory );
131 cfg.setEntityNotFoundDelegate( ejb3EntityNotFoundDelegate );
132 listenerConfigurator = new EventListenerConfigurator( this );
133 }
134
135 /**
136 * Used to inject a datasource object as the connection provider.
137 * If used, be sure to <b>not override</b> the hibernate.connection.provider_class
138 * property
139 */
140 public void setDataSource(DataSource ds) {
141 if ( ds != null ) {
142 Map cpInjection = new HashMap();
143 cpInjection.put( "dataSource", ds );
144 ( (InjectionSettingsFactory) settingsFactory ).setConnectionProviderInjectionData( cpInjection );
145 this.setProperty( Environment.CONNECTION_PROVIDER, InjectedDataSourceConnectionProvider.class.getName() );
146 }
147 }
148
149 /**
150 * create a factory from a parsed persistence.xml
151 * Especially the scanning of classes and additional jars is done already at this point.
152 */
153 private Ejb3Configuration configure(PersistenceMetadata metadata, Map overrides) {
154 log.debug( "Creating Factory: " + metadata.getName() );
155
156 Map workingVars = new HashMap();
157 workingVars.put( HibernatePersistence.PERSISTENCE_UNIT_NAME, metadata.getName() );
158
159 if ( StringHelper.isNotEmpty( metadata.getJtaDatasource() ) ) {
160 this.setProperty( Environment.DATASOURCE, metadata.getJtaDatasource() );
161 }
162 else if ( StringHelper.isNotEmpty( metadata.getNonJtaDatasource() ) ) {
163 this.setProperty( Environment.DATASOURCE, metadata.getNonJtaDatasource() );
164 }
165 defineTransactionType( metadata.getTransactionType(), workingVars );
166 if ( metadata.getClasses().size() > 0 ) {
167 workingVars.put( HibernatePersistence.CLASS_NAMES, metadata.getClasses() );
168 }
169 if ( metadata.getPackages().size() > 0 ) {
170 workingVars.put( HibernatePersistence.PACKAGE_NAMES, metadata.getPackages() );
171 }
172 if ( metadata.getMappingFiles().size() > 0 ) {
173 workingVars.put( HibernatePersistence.XML_FILE_NAMES, metadata.getMappingFiles() );
174 }
175 if ( metadata.getHbmfiles().size() > 0 ) {
176 workingVars.put( HibernatePersistence.HBXML_FILES, metadata.getHbmfiles() );
177 }
178 Properties props = new Properties();
179 props.putAll( metadata.getProps() );
180 if ( overrides != null ) {
181 for ( Map.Entry entry : (Set<Map.Entry>) overrides.entrySet() ) {
182 Object value = entry.getValue();
183 props.put( entry.getKey(), value == null ? "" : value ); //alter null, not allowed in properties
184 }
185 }
186 configure( props, workingVars );
187 return this;
188 }
189
190 /**
191 * Build the configuration from an entity manager name and given the
192 * appropriate extra properties. Those properties override the one get through
193 * the peristence.xml file.
194 * If the persistence unit name is not found or does not match the Persistence Provider, null is returned
195 *
196 * @param persistenceUnitName persistence unit name
197 * @param integration properties passed to the persistence provider
198 * @return configured Ejb3Configuration or null if no persistence unit match
199 */
200 public Ejb3Configuration configure(String persistenceUnitName, Map integration) {
201 try {
202 log.debug( "Look up for persistence unit: " + persistenceUnitName );
203 integration = integration == null ?
204 CollectionHelper.EMPTY_MAP :
205 Collections.unmodifiableMap( integration );
206 Enumeration<URL> xmls = Thread.currentThread()
207 .getContextClassLoader()
208 .getResources( "META-INF/persistence.xml" );
209 if ( ! xmls.hasMoreElements() ) {
210 log.info( "Could not find any META-INF/persistence.xml file in the classpath");
211 }
212 while ( xmls.hasMoreElements() ) {
213 URL url = xmls.nextElement();
214 log.trace( "Analyse of persistence.xml: " + url );
215 List<PersistenceMetadata> metadataFiles = PersistenceXmlLoader.deploy(
216 url,
217 integration,
218 cfg.getEntityResolver(),
219 PersistenceUnitTransactionType.RESOURCE_LOCAL );
220 for ( PersistenceMetadata metadata : metadataFiles ) {
221 log.trace( metadata.toString() );
222
223 if ( metadata.getProvider() == null || IMPLEMENTATION_NAME.equalsIgnoreCase(
224 metadata.getProvider()
225 ) ) {
226 //correct provider
227
228 //lazy compute the visitor if possible to avoid useless exceptions if an unexpected state happens
229 JarVisitor visitor = null;
230
231 if ( metadata.getName() == null ) {
232 visitor = getMainJarVisitor( url, metadata, integration );
233 metadata.setName( visitor.getUnqualifiedJarName() );
234 }
235 if ( persistenceUnitName == null && xmls.hasMoreElements() ) {
236 throw new PersistenceException( "No name provided and several persistence units found" );
237 }
238 else if ( persistenceUnitName == null || metadata.getName().equals( persistenceUnitName ) ) {
239 if (visitor == null) visitor = getMainJarVisitor( url, metadata, integration );
240 addMetadataFromVisitor( visitor, metadata );
241 JarVisitor.Filter[] otherXmlFilter = getFilters( metadata, integration, false );
242 for ( String jarFile : metadata.getJarFiles() ) {
243 visitor = JarVisitor.getVisitor( jarFile, otherXmlFilter );
244 addMetadataFromVisitor( visitor, metadata );
245 }
246 return configure( metadata, integration );
247 }
248 }
249 }
250 }
251 return null;
252 }
253 catch (Exception e) {
254 if ( e instanceof PersistenceException) {
255 throw (PersistenceException) e;
256 }
257 else {
258 throw new PersistenceException( e );
259 }
260 }
261 }
262
263 private JarVisitor getMainJarVisitor(URL url, PersistenceMetadata metadata, Map integration) {
264 URL jarURL = JarVisitor.getJarURLFromURLEntry( url, "/META-INF/persistence.xml" );
265 JarVisitor.Filter[] persistenceXmlFilter = getFilters( metadata, integration, metadata.getExcludeUnlistedClasses() );
266 JarVisitor visitor = JarVisitor.getVisitor( jarURL, persistenceXmlFilter );
267 return visitor;
268 }
269
270 private static void addMetadataFromVisitor(JarVisitor visitor, PersistenceMetadata metadata) throws IOException {
271 Set[] entries = visitor.getMatchingEntries();
272 JarVisitor.Filter[] filters = visitor.getFilters();
273 int size = filters.length;
274 List<String> classes = metadata.getClasses();
275 List<String> packages = metadata.getPackages();
276 List<NamedInputStream> hbmFiles = metadata.getHbmfiles();
277 for ( int index = 0; index < size ; index++ ) {
278 Iterator homogeneousEntry = entries[index].iterator();
279 while ( homogeneousEntry.hasNext() ) {
280 JarVisitor.Entry entry = (JarVisitor.Entry) homogeneousEntry.next();
281 if ( filters[index] instanceof JarVisitor.ClassFilter ) {
282 //TODO only add entry if there is annotations (Javassist)
283 classes.add( entry.getName() );
284 }
285 else if ( filters[index] instanceof JarVisitor.PackageFilter ) {
286 packages.add( entry.getName() );
287 }
288 else if ( filters[index] instanceof JarVisitor.FileFilter ) {
289 hbmFiles.add( new NamedInputStream( entry.getName(), entry.getInputStream() ) );
290 metadata.getMappingFiles().remove( entry.getName() );
291 }
292 }
293 }
294 }
295
296 /**
297 * Process configuration from a PersistenceUnitInfo object
298 * Typically called by the container
299 */
300 public Ejb3Configuration configure(PersistenceUnitInfo info, Map integration) {
301 if ( log.isDebugEnabled() ) {
302 log.debug( "Processing " + LogHelper.logPersistenceUnitInfo( info ) );
303 }
304 else {
305 log.info( "Processing PersistenceUnitInfo [\n\tname: " + info.getPersistenceUnitName() + "\n\t...]" );
306 }
307
308 integration = integration != null ? Collections.unmodifiableMap( integration ) : CollectionHelper.EMPTY_MAP;
309 String provider = (String) integration.get( HibernatePersistence.PROVIDER );
310 if ( provider == null ) provider = info.getPersistenceProviderClassName();
311 if ( provider != null && ! provider.trim().startsWith( IMPLEMENTATION_NAME ) ) {
312 log.info( "Required a different provider: " + provider );
313 return null;
314 }
315 if ( info.getClassLoader() == null ) {
316 throw new IllegalStateException(
317 "[PersistenceUnit: " + info.getPersistenceUnitName() == null ? "" : info.getPersistenceUnitName()
318 + "] " + "PersistenceUnitInfo.getClassLoader() id null" );
319 }
320 //set the classloader
321 Thread thread = Thread.currentThread();
322 ClassLoader contextClassLoader = thread.getContextClassLoader();
323 boolean sameClassLoader = info.getClassLoader().equals( contextClassLoader );
324 if ( ! sameClassLoader ) {
325 overridenClassLoader = info.getClassLoader();
326 thread.setContextClassLoader( overridenClassLoader );
327 }
328 else {
329 overridenClassLoader = null;
330 }
331
332 try {
333 Map workingVars = new HashMap();
334 workingVars.put( HibernatePersistence.PERSISTENCE_UNIT_NAME, info.getPersistenceUnitName() );
335 List<String> entities = new ArrayList<String>( 50 );
336 if ( info.getManagedClassNames() != null ) entities.addAll( info.getManagedClassNames() );
337 List<NamedInputStream> hbmFiles = new ArrayList<NamedInputStream>();
338 List<String> packages = new ArrayList<String>();
339 List<String> xmlFiles = new ArrayList<String>( 50 );
340 if ( info.getMappingFileNames() != null ) xmlFiles.addAll( info.getMappingFileNames() );
341 //Should always be true if the container is not dump
342 boolean searchForORMFiles = ! xmlFiles.contains( META_INF_ORM_XML );
343
344 boolean[] detectArtifactForOtherJars = getDetectedArtifacts( info.getProperties(), null, false );
345 boolean[] detectArtifactForMainJar = getDetectedArtifacts( info.getProperties(), null, info.excludeUnlistedClasses() );
346 for ( URL jar : info.getJarFileUrls() ) {
347 if ( detectArtifactForOtherJars[0] ) scanForClasses( jar, packages, entities );
348 if ( detectArtifactForOtherJars[1] ) scanForXmlFiles( jar, hbmFiles, searchForORMFiles );
349 }
350 if ( detectArtifactForMainJar[0] ) scanForClasses( info.getPersistenceUnitRootUrl(), packages, entities );
351 if ( detectArtifactForMainJar[1] )
352 scanForXmlFiles( info.getPersistenceUnitRootUrl(), hbmFiles, searchForORMFiles );
353
354 Properties properties = info.getProperties() != null ?
355 info.getProperties() :
356 new Properties();
357 ConfigurationHelper.overrideProperties( properties, integration );
358
359 //FIXME entities is used to enhance classes and to collect annotated entities this should not be mixed
360 //fill up entities with the on found in xml files
361 addXMLEntities( xmlFiles, info, entities );
362
363 //FIXME send the appropriate entites.
364 if ( "true".equalsIgnoreCase( properties.getProperty( HibernatePersistence.USE_CLASS_ENHANCER ) ) ) {
365 info.addTransformer( new InterceptFieldClassFileTransformer( entities ) );
366 }
367
368 workingVars.put( HibernatePersistence.CLASS_NAMES, entities );
369 workingVars.put( HibernatePersistence.PACKAGE_NAMES, packages );
370 workingVars.put( HibernatePersistence.XML_FILE_NAMES, xmlFiles );
371 if ( hbmFiles.size() > 0 ) workingVars.put( HibernatePersistence.HBXML_FILES, hbmFiles );
372
373 //datasources
374 Boolean isJTA = null;
375 boolean overridenDatasource = false;
376 if ( integration.containsKey( HibernatePersistence.JTA_DATASOURCE ) ) {
377 String dataSource = (String) integration.get( HibernatePersistence.JTA_DATASOURCE );
378 overridenDatasource = true;
379 properties.setProperty( Environment.DATASOURCE, dataSource );
380 isJTA = Boolean.TRUE;
381 }
382 if ( integration.containsKey( HibernatePersistence.NON_JTA_DATASOURCE ) ) {
383 String dataSource = (String) integration.get( HibernatePersistence.NON_JTA_DATASOURCE );
384 overridenDatasource = true;
385 properties.setProperty( Environment.DATASOURCE, dataSource );
386 if (isJTA == null) isJTA = Boolean.FALSE;
387 }
388
389 if ( ! overridenDatasource && ( info.getJtaDataSource() != null || info.getNonJtaDataSource() != null ) ) {
390 isJTA = info.getJtaDataSource() != null ? Boolean.TRUE : Boolean.FALSE;
391 this.setDataSource(
392 isJTA ? info.getJtaDataSource() : info.getNonJtaDataSource()
393 );
394 this.setProperty(
395 Environment.CONNECTION_PROVIDER, InjectedDataSourceConnectionProvider.class.getName()
396 );
397 }
398 /*
399 * If explicit type => use it
400 * If a JTA DS is used => JTA transaction,
401 * if a non JTA DS is used => RESOURCe_LOCAL
402 * if none, set to JavaEE default => JTA transaction
403 */
404 PersistenceUnitTransactionType transactionType = info.getTransactionType();
405 if (transactionType == null) {
406 if (isJTA == Boolean.TRUE) {
407 transactionType = PersistenceUnitTransactionType.JTA;
408 }
409 else if ( isJTA == Boolean.FALSE ) {
410 transactionType = PersistenceUnitTransactionType.RESOURCE_LOCAL;
411 }
412 else {
413 transactionType = PersistenceUnitTransactionType.JTA;
414 }
415 }
416 defineTransactionType( transactionType, workingVars );
417 configure( properties, workingVars );
418 }
419 finally {
420 //After EMF, set the CCL back
421 if ( ! sameClassLoader ) {
422 thread.setContextClassLoader( contextClassLoader );
423 }
424 }
425 return this;
426 }
427
428 private void addXMLEntities(List<String> xmlFiles, PersistenceUnitInfo info, List<String> entities) {
429 //TODO handle inputstream related hbm files
430 ClassLoader newTempClassLoader = info.getNewTempClassLoader();
431 if (newTempClassLoader == null) {
432 log.warn( "Persistence provider caller does not implements the EJB3 spec correctly. PersistenceUnitInfo.getNewTempClassLoader() is null." );
433 return;
434 }
435 XMLHelper xmlHelper = new XMLHelper();
436 List errors = new ArrayList();
437 SAXReader saxReader = xmlHelper.createSAXReader( "XML InputStream", errors, cfg.getEntityResolver() );
438 try {
439 saxReader.setFeature( "http://apache.org/xml/features/validation/schema", true );
440 //saxReader.setFeature( "http://apache.org/xml/features/validation/dynamic", true );
441 //set the default schema locators
442 saxReader.setProperty( "http://apache.org/xml/properties/schema/external-schemaLocation",
443 "http://java.sun.com/xml/ns/persistence/orm orm_1_0.xsd");
444 }
445 catch (SAXException e) {
446 saxReader.setValidation( false );
447 }
448
449 for ( String xmlFile : xmlFiles ) {
450
451 InputStream resourceAsStream = newTempClassLoader.getResourceAsStream( xmlFile );
452 if (resourceAsStream == null) continue;
453 BufferedInputStream is = new BufferedInputStream( resourceAsStream );
454 try {
455 errors.clear();
456 org.dom4j.Document doc = saxReader.read( is );
457 if ( errors.size() != 0 ) {
458 throw new MappingException( "invalid mapping: " + xmlFile, (Throwable) errors.get( 0 ) );
459 }
460 Element rootElement = doc.getRootElement();
461 if ( rootElement != null && "entity-mappings".equals( rootElement.getName() ) ) {
462 Element element = rootElement.element( "package" );
463 String defaultPackage = element != null ? element.getTextTrim() : null;
464 List<Element> elements = rootElement.elements( "entity" );
465 for (Element subelement : elements ) {
466 String classname = XMLContext.buildSafeClassName( subelement.attributeValue( "class" ), defaultPackage );
467 if ( ! entities.contains( classname ) ) {
468 entities.add( classname );
469 }
470 }
471 elements = rootElement.elements( "mapped-superclass" );
472 for (Element subelement : elements ) {
473 String classname = XMLContext.buildSafeClassName( subelement.attributeValue( "class" ), defaultPackage );
474 if ( ! entities.contains( classname ) ) {
475 entities.add( classname );
476 }
477 }
478 elements = rootElement.elements( "embeddable" );
479 for (Element subelement : elements ) {
480 String classname = XMLContext.buildSafeClassName( subelement.attributeValue( "class" ), defaultPackage );
481 if ( ! entities.contains( classname ) ) {
482 entities.add( classname );
483 }
484 }
485 }
486 else if ( rootElement != null && "hibernate-mappings".equals( rootElement.getName() ) ) {
487 //FIXME include hbm xml entities to enhance them but entities is also used to collect annotated entities
488 }
489 }
490 catch (DocumentException e) {
491 throw new MappingException( "Could not parse mapping document in input stream", e );
492 }
493 finally {
494 try {
495 is.close();
496 }
497 catch (IOException ioe) {
498 log.warn( "Could not close input stream", ioe );
499 }
500 }
501 }
502 }
503
504 private void defineTransactionType(Object overridenTxType, Map workingVars) {
505 if ( overridenTxType == null ) {
506 // if ( transactionType == null ) {
507 // transactionType = PersistenceUnitTransactionType.JTA; //this is the default value
508 // }
509 //nothing to override
510 }
511 else if ( overridenTxType instanceof String ) {
512 transactionType = PersistenceXmlLoader.getTransactionType( (String) overridenTxType );
513 }
514 else if ( overridenTxType instanceof PersistenceUnitTransactionType ) {
515 transactionType = (PersistenceUnitTransactionType) overridenTxType;
516 }
517 else {
518 throw new PersistenceException( getExceptionHeader( workingVars ) +
519 HibernatePersistence.TRANSACTION_TYPE + " of the wrong class type"
520 + ": " + overridenTxType.getClass()
521 );
522 }
523
524 }
525
526 public Ejb3Configuration setProperty(String key, String value) {
527 cfg.setProperty( key, value );
528 return this;
529 }
530
531 private boolean[] getDetectedArtifacts(Properties properties, Map overridenProperties, boolean excludeIfNotOverriden) {
532 boolean[] result = new boolean[2];
533 result[0] = false; //detect classes
534 result[1] = false; //detect hbm
535 String detect = overridenProperties != null ?
536 (String) overridenProperties.get( HibernatePersistence.AUTODETECTION ) :
537 null;
538 detect = detect == null ?
539 properties.getProperty( HibernatePersistence.AUTODETECTION) :
540 detect;
541 if (detect == null && excludeIfNotOverriden) {
542 //not overriden through HibernatePersistence.AUTODETECTION so we comply with the spec excludeUnlistedClasses
543 return result;
544 }
545 else if (detect == null){
546 detect = "class,hbm";
547 }
548 StringTokenizer st = new StringTokenizer( detect, ", ", false );
549 while ( st.hasMoreElements() ) {
550 String element = (String) st.nextElement();
551 if ( "class".equalsIgnoreCase( element ) ) result[0] = true;
552 if ( "hbm".equalsIgnoreCase( element ) ) result[1] = true;
553 }
554 log.debug( "Detect class: " + result[0] + "; detect hbm: " + result[1] );
555 return result;
556 }
557
558 private JarVisitor.Filter[] getFilters(PersistenceMetadata metadata, Map overridenProperties, boolean excludeIfNotOverriden) {
559 Properties properties = metadata.getProps();
560 final List<String> mappingFiles = metadata.getMappingFiles();
561 boolean[] result = getDetectedArtifacts( properties, overridenProperties, excludeIfNotOverriden );
562
563 int size = ( result[0] ? 2 : 0 ) + 1; //class involves classes and packages, xml files are always involved because of orm.xml
564 JarVisitor.Filter[] filters = new JarVisitor.Filter[size];
565 if ( result[0] ) {
566 filters[0] = new JarVisitor.PackageFilter( false, null ) {
567 public boolean accept(String javaElementName) {
568 return true;
569 }
570 };
571 filters[1] = new JarVisitor.ClassFilter(
572 false, new Class[]{
573 Entity.class,
574 MappedSuperclass.class,
575 Embeddable.class}
576 ) {
577 public boolean accept(String javaElementName) {
578 return true;
579 }
580 };
581 }
582 if ( result[1] ) {
583 filters[size - 1] = new JarVisitor.FileFilter( true ) {
584 public boolean accept(String javaElementName) {
585 return javaElementName.endsWith( "hbm.xml" )
586 || javaElementName.endsWith( META_INF_ORM_XML )
587 || mappingFiles.contains( javaElementName );
588 }
589 };
590 }
591 else {
592 filters[size - 1] = new JarVisitor.FileFilter( true ) {
593 public boolean accept(String javaElementName) {
594 return javaElementName.endsWith( META_INF_ORM_XML )
595 || mappingFiles.contains( javaElementName );
596 }
597 };
598 }
599 return filters;
600 }
601
602 private void scanForXmlFiles(URL jar, List<NamedInputStream> hbmxmls, final boolean searchforORMFiles) {
603 Iterator it = ArchiveBrowser.getBrowser(
604 jar, new ArchiveBrowser.Filter() {
605 public boolean accept(String filename) {
606 return filename.endsWith( ".hbm.xml" )
607 || (searchforORMFiles && filename.endsWith( META_INF_ORM_XML ) )
608 ;
609 }
610 }
611 );
612
613 while ( it.hasNext() ) {
614 InputStream stream = (InputStream) it.next();
615 hbmxmls.add( new NamedInputStream("", stream) );
616 }
617 }
618
619 private void scanForClasses(URL jar, List<String> packages, List<String> entities) {
620 Iterator it = null;
621 try {
622 it = ArchiveBrowser.getBrowser(
623 jar, new ArchiveBrowser.Filter() {
624 public boolean accept(String filename) {
625 return filename.endsWith( ".class" );
626 }
627 }
628 );
629 }
630 catch (RuntimeException e) {
631 throw new RuntimeException( "error trying to scan <jar-file>: " + jar.toString(), e );
632 }
633
634 // need to look into every entry in the archive to see if anybody has tags
635 // defined.
636 while ( it.hasNext() ) {
637 InputStream stream = (InputStream) it.next();
638 DataInputStream dstream = new DataInputStream( new BufferedInputStream( stream ) );
639 ClassFile cf = null;
640 try {
641 try {
642 cf = new ClassFile( dstream );
643 }
644 finally {
645 dstream.close();
646 stream.close();
647 }
648 }
649 catch (IOException e) {
650 throw new RuntimeException( e );
651 }
652 if ( cf.getName().endsWith( ".package-info" ) ) {
653 int idx = cf.getName().indexOf( ".package-info" );
654 String pkgName = cf.getName().substring( 0, idx );
655 log.info( "found package: " + pkgName );
656 packages.add( pkgName );
657 continue;
658 }
659
660 AnnotationsAttribute visible = (AnnotationsAttribute) cf.getAttribute( AnnotationsAttribute.visibleTag );
661 if ( visible != null ) {
662 boolean isEntity = visible.getAnnotation( Entity.class.getName() ) != null;
663 if ( isEntity ) {
664 log.info( "found EJB3 Entity bean: " + cf.getName() );
665 entities.add( cf.getName() );
666 }
667 boolean isEmbeddable = visible.getAnnotation( Embeddable.class.getName() ) != null;
668 if ( isEmbeddable ) {
669 log.info( "found EJB3 @Embeddable: " + cf.getName() );
670 entities.add( cf.getName() );
671 }
672 boolean isEmbeddableSuperclass = visible.getAnnotation( MappedSuperclass.class.getName() ) != null;
673 if ( isEmbeddableSuperclass ) {
674 log.info( "found EJB3 @MappedSuperclass: " + cf.getName() );
675 entities.add( cf.getName() );
676 }
677 }
678 }
679 }
680
681 /**
682 * create a factory from a list of properties and
683 * HibernatePersistence.CLASS_NAMES -> Collection<String> (use to list the classes from config files
684 * HibernatePersistence.PACKAGE_NAMES -> Collection<String> (use to list the mappings from config files
685 * HibernatePersistence.HBXML_FILES -> Collection<InputStream> (input streams of hbm files)
686 * HibernatePersistence.LOADED_CLASSES -> Collection<Class> (list of loaded classes)
687 * <p/>
688 * <b>Used by JBoss AS only</b>
689 * @deprecated use the Java Persistence API
690 */
691 // This is used directly by JBoss so don't remove until further notice. bill@jboss.org
692 public EntityManagerFactory createEntityManagerFactory(Map workingVars) {
693 Properties props = new Properties();
694 if ( workingVars != null ) {
695 props.putAll( workingVars );
696 //remove huge non String elements for a clean props
697 props.remove( HibernatePersistence.CLASS_NAMES );
698 props.remove( HibernatePersistence.PACKAGE_NAMES );
699 props.remove( HibernatePersistence.HBXML_FILES );
700 props.remove( HibernatePersistence.LOADED_CLASSES );
701 }
702 configure( props, workingVars );
703 return buildEntityManagerFactory();
704 }
705
706 /**
707 * Process configuration and build an EntityManagerFactory <b>when</b> the configuration is ready
708 * @deprecated
709 */
710 public EntityManagerFactory createEntityManagerFactory() {
711 configure( cfg.getProperties(), new HashMap() );
712 return buildEntityManagerFactory();
713 }
714
715 public EntityManagerFactory buildEntityManagerFactory() {
716 Thread thread = null;
717 ClassLoader contextClassLoader = null;
718 if (overridenClassLoader != null) {
719 thread = Thread.currentThread();
720 contextClassLoader = thread.getContextClassLoader();
721 thread.setContextClassLoader( overridenClassLoader );
722 }
723 try {
724 configure( (Properties)null, null );
725 NamingHelper.bind(this);
726 return new EntityManagerFactoryImpl(
727 cfg.buildSessionFactory(),
728 transactionType,
729 discardOnClose
730 );
731 }
732 catch (HibernateException e) {
733 throw new PersistenceException( e );
734 }
735 finally {
736 if (thread != null) {
737 thread.setContextClassLoader( contextClassLoader );
738 }
739 }
740 }
741
742 public Reference getReference() throws NamingException {
743 log.debug("Returning a Reference to the Ejb3Configuration");
744 ByteArrayOutputStream stream = new ByteArrayOutputStream();
745 ObjectOutput out = null;
746 byte[] serialized;
747 try {
748 out = new ObjectOutputStream( stream );
749 out.writeObject( this );
750 out.close();
751 serialized = stream.toByteArray();
752 stream.close();
753 }
754 catch (IOException e) {
755 NamingException namingException = new NamingException( "Unable to serialize Ejb3Configuration" );
756 namingException.setRootCause( e );
757 throw namingException;
758 }
759
760 return new Reference(
761 Ejb3Configuration.class.getName(),
762 new BinaryRefAddr("object", serialized ),
763 Ejb3ConfigurationObjectFactory.class.getName(),
764 null
765 );
766 }
767
768 /**
769 * create a factory from a canonical workingVars map and the overriden properties
770 *
771 */
772 private Ejb3Configuration configure(
773 Properties properties, Map workingVars
774 ) {
775 //TODO check for people calling more than once this method (except buildEMF)
776 if (isConfigurationProcessed) return this;
777 isConfigurationProcessed = true;
778 Properties preparedProperties = prepareProperties( properties, workingVars );
779 if ( workingVars == null ) workingVars = CollectionHelper.EMPTY_MAP;
780
781 if ( preparedProperties.containsKey( HibernatePersistence.CFG_FILE ) ) {
782 String cfgFileName = preparedProperties.getProperty( HibernatePersistence.CFG_FILE );
783 cfg.configure( cfgFileName );
784 }
785
786 cfg.addProperties( preparedProperties ); //persistence.xml has priority over hibernate.Cfg.xml
787
788 addClassesToSessionFactory( workingVars );
789
790 //processes specific properties
791 List<String> jaccKeys = new ArrayList<String>();
792
793
794 Interceptor defaultInterceptor = DEFAULT_CONFIGURATION.getInterceptor();
795 NamingStrategy defaultNamingStrategy = DEFAULT_CONFIGURATION.getNamingStrategy();
796
797 Iterator propertyIt = preparedProperties.keySet().iterator();
798 while ( propertyIt.hasNext() ) {
799 Object uncastObject = propertyIt.next();
800 //had to be safe
801 if ( uncastObject != null && uncastObject instanceof String ) {
802 String propertyKey = (String) uncastObject;
803 if ( propertyKey.startsWith( HibernatePersistence.CLASS_CACHE_PREFIX ) ) {
804 setCacheStrategy( propertyKey, preparedProperties, true, workingVars );
805 }
806 else if ( propertyKey.startsWith( HibernatePersistence.COLLECTION_CACHE_PREFIX ) ) {
807 setCacheStrategy( propertyKey, preparedProperties, false, workingVars );
808 }
809 else if ( propertyKey.startsWith( HibernatePersistence.JACC_PREFIX )
810 && ! ( propertyKey.equals( HibernatePersistence.JACC_CONTEXT_ID )
811 || propertyKey.equals( HibernatePersistence.JACC_ENABLED ) ) ) {
812 jaccKeys.add( propertyKey );
813 }
814 }
815 }
816 if ( preparedProperties.containsKey( HibernatePersistence.INTERCEPTOR )
817 && ( cfg.getInterceptor() == null
818 || cfg.getInterceptor().equals( defaultInterceptor ) ) ) {
819 //cfg.setInterceptor has precedence over configuration file
820 String interceptorName = preparedProperties.getProperty( HibernatePersistence.INTERCEPTOR );
821 try {
822 Class interceptor = classForName( interceptorName );
823 cfg.setInterceptor( (Interceptor) interceptor.newInstance() );
824 }
825 catch (ClassNotFoundException e) {
826 throw new PersistenceException(
827 getExceptionHeader(workingVars) + "Unable to find interceptor class: " + interceptorName, e
828 );
829 }
830 catch (IllegalAccessException e) {
831 throw new PersistenceException(
832 getExceptionHeader(workingVars) + "Unable to access interceptor class: " + interceptorName, e
833 );
834 }
835 catch (InstantiationException e) {
836 throw new PersistenceException(
837 getExceptionHeader(workingVars) + "Unable to instanciate interceptor class: " + interceptorName, e
838 );
839 }
840 catch (ClassCastException e) {
841 throw new PersistenceException(
842 getExceptionHeader(workingVars) + "Interceptor class does not implement Interceptor interface: " + interceptorName, e
843 );
844 }
845 }
846 if ( preparedProperties.containsKey( HibernatePersistence.NAMING_STRATEGY )
847 && ( cfg.getNamingStrategy() == null
848 || cfg.getNamingStrategy().equals( defaultNamingStrategy ) ) ) {
849 //cfg.setNamingStrategy has precedence over configuration file
850 String namingStrategyName = preparedProperties.getProperty( HibernatePersistence.NAMING_STRATEGY );
851 try {
852 Class namingStragegy = classForName( namingStrategyName );
853 cfg.setNamingStrategy( (NamingStrategy) namingStragegy.newInstance() );
854 }
855 catch (ClassNotFoundException e) {
856 throw new PersistenceException(
857 getExceptionHeader(workingVars) + "Unable to find naming strategy class: " + namingStrategyName, e
858 );
859 }
860 catch (IllegalAccessException e) {
861 throw new PersistenceException(
862 getExceptionHeader(workingVars) + "Unable to access naming strategy class: " + namingStrategyName, e
863 );
864 }
865 catch (InstantiationException e) {
866 throw new PersistenceException(
867 getExceptionHeader(workingVars) + "Unable to instanciate naming strategy class: " + namingStrategyName, e
868 );
869 }
870 catch (ClassCastException e) {
871 throw new PersistenceException(
872 getExceptionHeader(workingVars) + "Naming strategyy class does not implement NmaingStrategy interface: " + namingStrategyName,
873 e
874 );
875 }
876 }
877
878 if ( jaccKeys.size() > 0 ) {
879 addSecurity( jaccKeys, preparedProperties, workingVars );
880 }
881
882 //initialize listeners
883 listenerConfigurator.setProperties( preparedProperties );
884 listenerConfigurator.configure();
885
886 //some spec compliance checking
887 //TODO centralize that?
888 if ( ! "true".equalsIgnoreCase( cfg.getProperty( Environment.AUTOCOMMIT ) ) ) {
889 log.warn( Environment.AUTOCOMMIT + " = false break the EJB3 specification" );
890 }
891 discardOnClose = preparedProperties.getProperty( HibernatePersistence.DISCARD_PC_ON_CLOSE )
892 .equals( "true" );
893 return this;
894 }
895
896 private void addClassesToSessionFactory(Map workingVars) {
897 if ( workingVars.containsKey( HibernatePersistence.CLASS_NAMES ) ) {
898 Collection<String> classNames = (Collection<String>) workingVars.get(
899 HibernatePersistence.CLASS_NAMES
900 );
901 addNamedAnnotatedClasses( this, classNames, workingVars );
902 }
903 //TODO apparently only used for Tests, get rid of it?
904 if ( workingVars.containsKey( HibernatePersistence.LOADED_CLASSES ) ) {
905 Collection<Class> classes = (Collection<Class>) workingVars.get( HibernatePersistence.LOADED_CLASSES );
906 for ( Class clazz : classes ) {
907 cfg.addAnnotatedClass( clazz );
908 }
909 }
910 if ( workingVars.containsKey( HibernatePersistence.PACKAGE_NAMES ) ) {
911 Collection<String> packages = (Collection<String>) workingVars.get(
912 HibernatePersistence.PACKAGE_NAMES
913 );
914 for ( String pkg : packages ) {
915 cfg.addPackage( pkg );
916 }
917 }
918 if ( workingVars.containsKey( HibernatePersistence.XML_FILE_NAMES ) ) {
919 Collection<String> xmlFiles = (Collection<String>) workingVars.get(
920 HibernatePersistence.XML_FILE_NAMES
921 );
922 for ( String xmlFile : xmlFiles ) {
923 Boolean useMetaInf = null;
924 try {
925 if ( xmlFile.endsWith( META_INF_ORM_XML ) ) useMetaInf = true;
926 cfg.addResource( xmlFile );
927 }
928 catch( MappingNotFoundException e ) {
929 if ( ! xmlFile.endsWith( META_INF_ORM_XML ) ) {
930 throw new PersistenceException( getExceptionHeader(workingVars)
931 + "Unable to find XML mapping file in classpath: " + xmlFile);
932 }
933 else {
934 useMetaInf = false;
935 //swallow it, the META-INF/orm.xml is optional
936 }
937 }
938 catch( MappingException me ) {
939 throw new PersistenceException( getExceptionHeader(workingVars)
940 + "Error while reading JPA XML file: " + xmlFile, me);
941 }
942 if ( log.isInfoEnabled() ) {
943 if ( Boolean.TRUE.equals( useMetaInf ) ) {
944 log.info( getExceptionHeader( workingVars ) + META_INF_ORM_XML + " found");
945 }
946 else if (Boolean.FALSE.equals( useMetaInf ) ) {
947 log.info( getExceptionHeader( workingVars ) + "no " + META_INF_ORM_XML + " found");
948 }
949 }
950 }
951 }
952 if ( workingVars.containsKey( HibernatePersistence.HBXML_FILES ) ) {
953 Collection<NamedInputStream> hbmXmlFiles = (Collection<NamedInputStream>) workingVars.get(
954 HibernatePersistence.HBXML_FILES
955 );
956 for ( NamedInputStream is : hbmXmlFiles ) {
957 try {
958 //addInputStream has the responsibility to close the stream
959 cfg.addInputStream( new BufferedInputStream( is.getStream() ) );
960 }
961 catch (MappingException me) {
962 //try our best to give the file name
963 if ( StringHelper.isEmpty( is.getName() ) ) {
964 throw me;
965 }
966 else {
967 throw new MappingException("Error while parsing file: " + is.getName(), me );
968 }
969 }
970 }
971 }
972 }
973
974 private String getExceptionHeader(Map workingVars) {
975 if ( workingVars != null ) {
976 String puName = (String) workingVars.get( HibernatePersistence.PERSISTENCE_UNIT_NAME);
977 puName = puName == null ? "" : puName;
978 String header = "[PersistenceUnit: " + puName + "] ";
979 return header;
980 }
981 else {
982 return "";
983 }
984 }
985
986 private Properties prepareProperties(Properties properties, Map workingVars) {
987 Properties preparedProperties = new Properties();
988
989 //defaults different to Hibernate
990 preparedProperties.setProperty( Environment.RELEASE_CONNECTIONS, "auto" );
991 preparedProperties.setProperty( Environment.JPAQL_STRICT_COMPLIANCE, "true" );
992 //settings that always apply to a compliant EJB3
993 preparedProperties.setProperty( Environment.AUTOCOMMIT, "true" );
994 preparedProperties.setProperty( Environment.USE_IDENTIFIER_ROLLBACK, "false" );
995 preparedProperties.setProperty( Environment.FLUSH_BEFORE_COMPLETION, "false" );
996 preparedProperties.setProperty( HibernatePersistence.DISCARD_PC_ON_CLOSE, "false" );
997
998 //override the new defaults with the user defined ones
999 //copy programmatically defined properties
1000 if ( cfg.getProperties() != null ) preparedProperties.putAll( cfg.getProperties() );
1001 //copy them co;ing from configuration
1002 if ( properties != null ) preparedProperties.putAll( properties );
1003 //note we don't copy cfg.xml properties, since they have to be overriden
1004
1005 if (transactionType == null) {
1006 //if it has not been set, the user use a programmatic way
1007 transactionType = PersistenceUnitTransactionType.RESOURCE_LOCAL;
1008 }
1009 defineTransactionType(
1010 preparedProperties.getProperty( HibernatePersistence.TRANSACTION_TYPE ),
1011 workingVars
1012 );
1013 boolean hasTxStrategy = StringHelper.isNotEmpty(
1014 preparedProperties.getProperty( Environment.TRANSACTION_STRATEGY )
1015 );
1016 if ( ! hasTxStrategy && transactionType == PersistenceUnitTransactionType.JTA ) {
1017 preparedProperties.setProperty(
1018 Environment.TRANSACTION_STRATEGY, JoinableCMTTransactionFactory.class.getName()
1019 );
1020 }
1021 else if ( ! hasTxStrategy && transactionType == PersistenceUnitTransactionType.RESOURCE_LOCAL ) {
1022 preparedProperties.setProperty( Environment.TRANSACTION_STRATEGY, JDBCTransactionFactory.class.getName() );
1023 }
1024 if ( hasTxStrategy ) {
1025 log.warn(
1026 "Overriding " + Environment.TRANSACTION_STRATEGY + " is dangerous, this might break the EJB3 specification implementation"
1027 );
1028 }
1029 if ( preparedProperties.getProperty( Environment.FLUSH_BEFORE_COMPLETION ).equals( "true" ) ) {
1030 preparedProperties.setProperty( Environment.FLUSH_BEFORE_COMPLETION, "false" );
1031 log.warn( "Defining " + Environment.FLUSH_BEFORE_COMPLETION + "=true ignored in HEM" );
1032 }
1033 return preparedProperties;
1034 }
1035
1036 private Class classForName(String className) throws ClassNotFoundException {
1037 return ReflectHelper.classForName( className, this.getClass() );
1038 }
1039
1040 private void setCacheStrategy(String propertyKey, Map properties, boolean isClass, Map workingVars) {
1041 String role = propertyKey.substring(
1042 ( isClass ? HibernatePersistence.CLASS_CACHE_PREFIX
1043 .length() : HibernatePersistence.COLLECTION_CACHE_PREFIX.length() )
1044 + 1
1045 );
1046 //dot size added
1047 String value = (String) properties.get( propertyKey );
1048 StringTokenizer params = new StringTokenizer( value, ";, " );
1049 if ( !params.hasMoreTokens() ) {
1050 StringBuilder error = new StringBuilder( "Illegal usage of " );
1051 error.append(
1052 isClass ? HibernatePersistence.CLASS_CACHE_PREFIX : HibernatePersistence.COLLECTION_CACHE_PREFIX
1053 );
1054 error.append( ": " ).append( propertyKey ).append( " " ).append( value );
1055 throw new PersistenceException( getExceptionHeader(workingVars) + error.toString() );
1056 }
1057 String usage = params.nextToken();
1058 String region = null;
1059 if ( params.hasMoreTokens() ) {
1060 region = params.nextToken();
1061 }
1062 if ( isClass ) {
1063 boolean lazyProperty = true;
1064 if ( params.hasMoreTokens() ) {
1065 lazyProperty = "all".equalsIgnoreCase( params.nextToken() );
1066 }
1067 cfg.setCacheConcurrencyStrategy( role, usage, region, lazyProperty );
1068 }
1069 else {
1070 cfg.setCollectionCacheConcurrencyStrategy( role, usage, region );
1071 }
1072 }
1073
1074 private void addSecurity(List<String> keys, Map properties, Map workingVars) {
1075 log.debug( "Adding security" );
1076 if ( !properties.containsKey( HibernatePersistence.JACC_CONTEXT_ID ) ) {
1077 throw new PersistenceException( getExceptionHeader(workingVars) +
1078 "Entities have been configured for JACC, but "
1079 + HibernatePersistence.JACC_CONTEXT_ID
1080 + " has not been set"
1081 );
1082 }
1083 String contextId = (String) properties.get( HibernatePersistence.JACC_CONTEXT_ID );
1084 setProperty( Environment.JACC_CONTEXTID, contextId );
1085
1086 int roleStart = HibernatePersistence.JACC_PREFIX.length() + 1;
1087
1088 for ( String key : keys ) {
1089 JACCConfiguration jaccCfg = new JACCConfiguration( contextId );
1090 try {
1091 String role = key.substring( roleStart, key.indexOf( '.', roleStart ) );
1092 int classStart = roleStart + role.length() + 1;
1093 String clazz = key.substring( classStart, key.length() );
1094 String actions = (String) properties.get( key );
1095 jaccCfg.addPermission( role, clazz, actions );
1096 }
1097 catch (IndexOutOfBoundsException e) {
1098 throw new PersistenceException( getExceptionHeader(workingVars) +
1099 "Illegal usage of " + HibernatePersistence.JACC_PREFIX + ": " + key );
1100 }
1101 }
1102 }
1103
1104 private void addNamedAnnotatedClasses(
1105 Ejb3Configuration cfg, Collection<String> classNames, Map workingVars
1106 ) {
1107 for ( String name : classNames ) {
1108 try {
1109 Class clazz = classForName( name );
1110 cfg.addAnnotatedClass( clazz );
1111 }
1112 catch (ClassNotFoundException cnfe) {
1113 Package pkg;
1114 try {
1115 pkg = classForName( name + ".package-info" ).getPackage();
1116 }
1117 catch (ClassNotFoundException e) {
1118 pkg = null;
1119 }
1120 if ( pkg == null ) {
1121 throw new PersistenceException( getExceptionHeader(workingVars) + "class or package not found", cnfe );
1122 }
1123 else {
1124 cfg.addPackage( name );
1125 }
1126 }
1127 }
1128 }
1129
1130
1131 public Settings buildSettings() throws HibernateException {
1132 Thread thread = null;
1133 ClassLoader contextClassLoader = null;
1134 if (overridenClassLoader != null) {
1135 thread = Thread.currentThread();
1136 contextClassLoader = thread.getContextClassLoader();
1137 thread.setContextClassLoader( overridenClassLoader );
1138 }
1139 try {
1140 return settingsFactory.buildSettings( cfg.getProperties() );
1141 }
1142 finally {
1143 if (thread != null) thread.setContextClassLoader( contextClassLoader );
1144 }
1145 }
1146
1147 public Ejb3Configuration addProperties(Properties props) {
1148 cfg.addProperties( props );
1149 return this;
1150 }
1151
1152 public Ejb3Configuration addAnnotatedClass(Class persistentClass) throws MappingException {
1153 Thread thread = null;
1154 ClassLoader contextClassLoader = null;
1155 if (overridenClassLoader != null) {
1156 thread = Thread.currentThread();
1157 contextClassLoader = thread.getContextClassLoader();
1158 thread.setContextClassLoader( overridenClassLoader );
1159 }
1160 try {
1161 cfg.addAnnotatedClass( persistentClass );
1162 return this;
1163 }
1164 finally {
1165 if (thread != null) thread.setContextClassLoader( contextClassLoader );
1166 }
1167 }
1168
1169 public Ejb3Configuration configure(String resource) throws HibernateException {
1170 Thread thread = null;
1171 ClassLoader contextClassLoader = null;
1172 if (overridenClassLoader != null) {
1173 thread = Thread.currentThread();
1174 contextClassLoader = thread.getContextClassLoader();
1175 thread.setContextClassLoader( overridenClassLoader );
1176 }
1177 try {
1178 Properties properties = new Properties();
1179 properties.setProperty( HibernatePersistence.CFG_FILE, resource);
1180 configure( properties, new HashMap() );
1181 return this;
1182 }
1183 finally {
1184 if (thread != null) thread.setContextClassLoader( contextClassLoader );
1185 }
1186 }
1187
1188 public Ejb3Configuration addPackage(String packageName) throws MappingException {
1189 Thread thread = null;
1190 ClassLoader contextClassLoader = null;
1191 if (overridenClassLoader != null) {
1192 thread = Thread.currentThread();
1193 contextClassLoader = thread.getContextClassLoader();
1194 thread.setContextClassLoader( overridenClassLoader );
1195 }
1196 try {
1197 cfg.addPackage( packageName );
1198 return this;
1199 }
1200 finally {
1201 if (thread != null) thread.setContextClassLoader( contextClassLoader );
1202 }
1203 }
1204
1205 public Ejb3Configuration addFile(String xmlFile) throws MappingException {
1206 Thread thread = null;
1207 ClassLoader contextClassLoader = null;
1208 if (overridenClassLoader != null) {
1209 thread = Thread.currentThread();
1210 contextClassLoader = thread.getContextClassLoader();
1211 thread.setContextClassLoader( overridenClassLoader );
1212 }
1213 try {
1214 cfg.addFile( xmlFile );
1215 return this;
1216 }
1217 finally {
1218 if (thread != null) thread.setContextClassLoader( contextClassLoader );
1219 }
1220 }
1221
1222 public Ejb3Configuration addClass(Class persistentClass) throws MappingException {
1223 Thread thread = null;
1224 ClassLoader contextClassLoader = null;
1225 if (overridenClassLoader != null) {
1226 thread = Thread.currentThread();
1227 contextClassLoader = thread.getContextClassLoader();
1228 thread.setContextClassLoader( overridenClassLoader );
1229 }
1230 try {
1231 cfg.addClass( persistentClass );
1232 return this;
1233 }
1234 finally {
1235 if (thread != null) thread.setContextClassLoader( contextClassLoader );
1236 }
1237 }
1238
1239 public Ejb3Configuration addFile(File xmlFile) throws MappingException {
1240 Thread thread = null;
1241 ClassLoader contextClassLoader = null;
1242 if (overridenClassLoader != null) {
1243 thread = Thread.currentThread();
1244 contextClassLoader = thread.getContextClassLoader();
1245 thread.setContextClassLoader( overridenClassLoader );
1246 }
1247 try {
1248 cfg.addFile( xmlFile );
1249 return this;
1250 }
1251 finally {
1252 if (thread != null) thread.setContextClassLoader( contextClassLoader );
1253 }
1254 }
1255
1256 public void buildMappings() {
1257 Thread thread = null;
1258 ClassLoader contextClassLoader = null;
1259 if (overridenClassLoader != null) {
1260 thread = Thread.currentThread();
1261 contextClassLoader = thread.getContextClassLoader();
1262 thread.setContextClassLoader( overridenClassLoader );
1263 }
1264 try {
1265 cfg.buildMappings();
1266 }
1267 finally {
1268 if (thread != null) thread.setContextClassLoader( contextClassLoader );
1269 }
1270 }
1271
1272 public Iterator getClassMappings() {
1273 Thread thread = null;
1274 ClassLoader contextClassLoader = null;
1275 if (overridenClassLoader != null) {
1276 thread = Thread.currentThread();
1277 contextClassLoader = thread.getContextClassLoader();
1278 thread.setContextClassLoader( overridenClassLoader );
1279 }
1280 try {
1281 return cfg.getClassMappings();
1282 }
1283 finally {
1284 if (thread != null) thread.setContextClassLoader( contextClassLoader );
1285 }
1286 }
1287
1288 public EventListeners getEventListeners() {
1289 return cfg.getEventListeners();
1290 }
1291
1292 SessionFactory buildSessionFactory() throws HibernateException {
1293 return cfg.buildSessionFactory();
1294 }
1295
1296 public Iterator getTableMappings() {
1297 return cfg.getTableMappings();
1298 }
1299
1300 public PersistentClass getClassMapping(String persistentClass) {
1301 return cfg.getClassMapping( persistentClass );
1302 }
1303
1304 public org.hibernate.mapping.Collection getCollectionMapping(String role) {
1305 return cfg.getCollectionMapping( role );
1306 }
1307
1308 public void setEntityResolver(EntityResolver entityResolver) {
1309 cfg.setEntityResolver( entityResolver );
1310 }
1311
1312 public Map getNamedQueries() {
1313 return cfg.getNamedQueries();
1314 }
1315
1316 public Interceptor getInterceptor() {
1317 return cfg.getInterceptor();
1318 }
1319
1320 public Properties getProperties() {
1321 return cfg.getProperties();
1322 }
1323
1324 public Ejb3Configuration setInterceptor(Interceptor interceptor) {
1325 cfg.setInterceptor( interceptor );
1326 return this;
1327 }
1328
1329 public Ejb3Configuration setProperties(Properties properties) {
1330 cfg.setProperties( properties );
1331 return this;
1332 }
1333
1334 public Map getFilterDefinitions() {
1335 return cfg.getFilterDefinitions();
1336 }
1337
1338 public void addFilterDefinition(FilterDefinition definition) {
1339 cfg.addFilterDefinition( definition );
1340 }
1341
1342 public void addAuxiliaryDatabaseObject(AuxiliaryDatabaseObject object) {
1343 cfg.addAuxiliaryDatabaseObject( object );
1344 }
1345
1346 public NamingStrategy getNamingStrategy() {
1347 return cfg.getNamingStrategy();
1348 }
1349
1350 public Ejb3Configuration setNamingStrategy(NamingStrategy namingStrategy) {
1351 cfg.setNamingStrategy( namingStrategy );
1352 return this;
1353 }
1354
1355 public void setListeners(String type, String[] listenerClasses) {
1356 cfg.setListeners( type, listenerClasses );
1357 }
1358
1359 public void setListeners(String type, Object[] listeners) {
1360 cfg.setListeners( type, listeners );
1361 }
1362
1363 /**
1364 * This API is intended to give a read-only configuration.
1365 * It is sueful when working with SchemaExport or any Configuration based
1366 * tool.
1367 * DO NOT update configuration through it.
1368 */
1369 public AnnotationConfiguration getHibernateConfiguration() {
1370 //TODO make it really read only (maybe through proxying)
1371 return cfg;
1372 }
1373
1374 public Ejb3Configuration addInputStream(InputStream xmlInputStream) throws MappingException {
1375 Thread thread = null;
1376 ClassLoader contextClassLoader = null;
1377 if (overridenClassLoader != null) {
1378 thread = Thread.currentThread();
1379 contextClassLoader = thread.getContextClassLoader();
1380 thread.setContextClassLoader( overridenClassLoader );
1381 }
1382 try {
1383 cfg.addInputStream( xmlInputStream );
1384 return this;
1385 }
1386 finally {
1387 if (thread != null) thread.setContextClassLoader( contextClassLoader );
1388 }
1389 }
1390
1391 public Ejb3Configuration addResource(String path) throws MappingException {
1392 Thread thread = null;
1393 ClassLoader contextClassLoader = null;
1394 if (overridenClassLoader != null) {
1395 thread = Thread.currentThread();
1396 contextClassLoader = thread.getContextClassLoader();
1397 thread.setContextClassLoader( overridenClassLoader );
1398 }
1399 try {
1400 cfg.addResource( path );
1401 return this;
1402 }
1403 finally {
1404 if (thread != null) thread.setContextClassLoader( contextClassLoader );
1405 }
1406 }
1407
1408 public Ejb3Configuration addResource(String path, ClassLoader classLoader) throws MappingException {
1409 cfg.addResource( path, classLoader );
1410 return this;
1411 }
1412 }