Save This Page
Home » hibernate-entity-src-20081106 » org.hibernate » ejb » [javadoc | source]
    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   }

Save This Page
Home » hibernate-entity-src-20081106 » org.hibernate » ejb » [javadoc | source]