Save This Page
Home » hibernate-distribution-3.3.1.GA-dist » org.hibernate » cfg » [javadoc | source]
    1   /*
    2    * Hibernate, Relational Persistence for Idiomatic Java
    3    *
    4    * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
    5    * indicated by the @author tags or express copyright attribution
    6    * statements applied by the authors.  All third-party contributions are
    7    * distributed under license by Red Hat Middleware LLC.
    8    *
    9    * This copyrighted material is made available to anyone wishing to use, modify,
   10    * copy, or redistribute it subject to the terms and conditions of the GNU
   11    * Lesser General Public License, as published by the Free Software Foundation.
   12    *
   13    * This program is distributed in the hope that it will be useful,
   14    * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   15    * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
   16    * for more details.
   17    *
   18    * You should have received a copy of the GNU Lesser General Public License
   19    * along with this distribution; if not, write to:
   20    * Free Software Foundation, Inc.
   21    * 51 Franklin Street, Fifth Floor
   22    * Boston, MA  02110-1301  USA
   23    *
   24    */
   25   package org.hibernate.cfg;
   26   
   27   import java.io.File;
   28   import java.io.FileInputStream;
   29   import java.io.FileNotFoundException;
   30   import java.io.FileOutputStream;
   31   import java.io.IOException;
   32   import java.io.InputStream;
   33   import java.io.ObjectInputStream;
   34   import java.io.Serializable;
   35   import java.io.StringReader;
   36   import java.lang.reflect.Array;
   37   import java.net.URL;
   38   import java.util.ArrayList;
   39   import java.util.Enumeration;
   40   import java.util.HashMap;
   41   import java.util.HashSet;
   42   import java.util.Iterator;
   43   import java.util.List;
   44   import java.util.ListIterator;
   45   import java.util.Map;
   46   import java.util.Properties;
   47   import java.util.Set;
   48   import java.util.TreeMap;
   49   import java.util.jar.JarFile;
   50   import java.util.zip.ZipEntry;
   51   
   52   import org.dom4j.Attribute;
   53   import org.dom4j.DocumentException;
   54   import org.dom4j.Element;
   55   import org.slf4j.Logger;
   56   import org.slf4j.LoggerFactory;
   57   import org.w3c.dom.Document;
   58   import org.xml.sax.EntityResolver;
   59   import org.xml.sax.InputSource;
   60   
   61   import org.hibernate.EmptyInterceptor;
   62   import org.hibernate.HibernateException;
   63   import org.hibernate.Interceptor;
   64   import org.hibernate.InvalidMappingException;
   65   import org.hibernate.MappingException;
   66   import org.hibernate.MappingNotFoundException;
   67   import org.hibernate.SessionFactory;
   68   import org.hibernate.SessionFactoryObserver;
   69   import org.hibernate.dialect.Dialect;
   70   import org.hibernate.dialect.MySQLDialect;
   71   import org.hibernate.dialect.function.SQLFunction;
   72   import org.hibernate.engine.FilterDefinition;
   73   import org.hibernate.engine.Mapping;
   74   import org.hibernate.event.AutoFlushEventListener;
   75   import org.hibernate.event.DeleteEventListener;
   76   import org.hibernate.event.DirtyCheckEventListener;
   77   import org.hibernate.event.EventListeners;
   78   import org.hibernate.event.EvictEventListener;
   79   import org.hibernate.event.FlushEntityEventListener;
   80   import org.hibernate.event.FlushEventListener;
   81   import org.hibernate.event.InitializeCollectionEventListener;
   82   import org.hibernate.event.LoadEventListener;
   83   import org.hibernate.event.LockEventListener;
   84   import org.hibernate.event.MergeEventListener;
   85   import org.hibernate.event.PersistEventListener;
   86   import org.hibernate.event.PostCollectionRecreateEventListener;
   87   import org.hibernate.event.PostCollectionRemoveEventListener;
   88   import org.hibernate.event.PostCollectionUpdateEventListener;
   89   import org.hibernate.event.PostDeleteEventListener;
   90   import org.hibernate.event.PostInsertEventListener;
   91   import org.hibernate.event.PostLoadEventListener;
   92   import org.hibernate.event.PostUpdateEventListener;
   93   import org.hibernate.event.PreCollectionRecreateEventListener;
   94   import org.hibernate.event.PreCollectionRemoveEventListener;
   95   import org.hibernate.event.PreCollectionUpdateEventListener;
   96   import org.hibernate.event.PreDeleteEventListener;
   97   import org.hibernate.event.PreInsertEventListener;
   98   import org.hibernate.event.PreLoadEventListener;
   99   import org.hibernate.event.PreUpdateEventListener;
  100   import org.hibernate.event.RefreshEventListener;
  101   import org.hibernate.event.ReplicateEventListener;
  102   import org.hibernate.event.SaveOrUpdateEventListener;
  103   import org.hibernate.id.IdentifierGenerator;
  104   import org.hibernate.id.PersistentIdentifierGenerator;
  105   import org.hibernate.impl.SessionFactoryImpl;
  106   import org.hibernate.mapping.AuxiliaryDatabaseObject;
  107   import org.hibernate.mapping.Collection;
  108   import org.hibernate.mapping.ForeignKey;
  109   import org.hibernate.mapping.IdentifierCollection;
  110   import org.hibernate.mapping.Index;
  111   import org.hibernate.mapping.PersistentClass;
  112   import org.hibernate.mapping.Property;
  113   import org.hibernate.mapping.RootClass;
  114   import org.hibernate.mapping.SimpleValue;
  115   import org.hibernate.mapping.Table;
  116   import org.hibernate.mapping.UniqueKey;
  117   import org.hibernate.proxy.EntityNotFoundDelegate;
  118   import org.hibernate.secure.JACCConfiguration;
  119   import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
  120   import org.hibernate.tool.hbm2ddl.TableMetadata;
  121   import org.hibernate.type.SerializationException;
  122   import org.hibernate.type.Type;
  123   import org.hibernate.util.ArrayHelper;
  124   import org.hibernate.util.CollectionHelper;
  125   import org.hibernate.util.ConfigHelper;
  126   import org.hibernate.util.PropertiesHelper;
  127   import org.hibernate.util.ReflectHelper;
  128   import org.hibernate.util.SerializationHelper;
  129   import org.hibernate.util.StringHelper;
  130   import org.hibernate.util.XMLHelper;
  131   
  132   /**
  133    * An instance of <tt>Configuration</tt> allows the application
  134    * to specify properties and mapping documents to be used when
  135    * creating a <tt>SessionFactory</tt>. Usually an application will create
  136    * a single <tt>Configuration</tt>, build a single instance of
  137    * <tt>SessionFactory</tt> and then instantiate <tt>Session</tt>s in
  138    * threads servicing client requests. The <tt>Configuration</tt> is meant
  139    * only as an initialization-time object. <tt>SessionFactory</tt>s are
  140    * immutable and do not retain any association back to the
  141    * <tt>Configuration</tt>.<br>
  142    * <br>
  143    * A new <tt>Configuration</tt> will use the properties specified in
  144    * <tt>hibernate.properties</tt> by default.
  145    *
  146    * @author Gavin King
  147    * @see org.hibernate.SessionFactory
  148    */
  149   public class Configuration implements Serializable {
  150   
  151   	private static Logger log = LoggerFactory.getLogger( Configuration.class );
  152   
  153   	protected Map classes;
  154   	protected Map imports;
  155   	protected Map collections;
  156   	protected Map tables;
  157   	protected List auxiliaryDatabaseObjects;
  158   	protected Map sqlFunctions;
  159   	protected Map namedQueries;
  160   	protected Map namedSqlQueries;
  161   	/**
  162   	 * Map<String, SqlResultSetMapping> result set name, result set description
  163   	 */
  164   	protected Map sqlResultSetMappings;
  165   	protected Map filterDefinitions;
  166   	protected List secondPasses;
  167   	protected List propertyReferences;
  168   //	protected List extendsQueue;
  169   	protected Map extendsQueue;
  170   	protected Map tableNameBinding;
  171   	protected Map columnNameBindingPerTable;
  172   	private Interceptor interceptor;
  173   	private Properties properties;
  174   	private EntityResolver entityResolver;
  175   	private EntityNotFoundDelegate entityNotFoundDelegate;
  176   
  177   	protected transient XMLHelper xmlHelper;
  178   	protected transient Map typeDefs;
  179   
  180   	protected NamingStrategy namingStrategy;
  181   
  182   	private EventListeners eventListeners;
  183   
  184   	protected final SettingsFactory settingsFactory;
  185   
  186   	private SessionFactoryObserver sessionFactoryObserver;
  187   
  188   	protected void reset() {
  189   		classes = new HashMap();
  190   		imports = new HashMap();
  191   		collections = new HashMap();
  192   		tables = new TreeMap();
  193   		namedQueries = new HashMap();
  194   		namedSqlQueries = new HashMap();
  195   		sqlResultSetMappings = new HashMap();
  196   		xmlHelper = new XMLHelper();
  197   		typeDefs = new HashMap();
  198   		propertyReferences = new ArrayList();
  199   		secondPasses = new ArrayList();
  200   		interceptor = EmptyInterceptor.INSTANCE;
  201   		properties = Environment.getProperties();
  202   		entityResolver = XMLHelper.DEFAULT_DTD_RESOLVER;
  203   		eventListeners = new EventListeners();
  204   		filterDefinitions = new HashMap();
  205   //		extendsQueue = new ArrayList();
  206   		extendsQueue = new HashMap();
  207   		auxiliaryDatabaseObjects = new ArrayList();
  208   		tableNameBinding = new HashMap();
  209   		columnNameBindingPerTable = new HashMap();
  210   		namingStrategy = DefaultNamingStrategy.INSTANCE;
  211   		sqlFunctions = new HashMap();
  212   	}
  213   
  214   	private transient Mapping mapping = buildMapping();
  215   
  216   
  217   
  218   	protected Configuration(SettingsFactory settingsFactory) {
  219   		this.settingsFactory = settingsFactory;
  220   		reset();
  221   	}
  222   
  223   	public Configuration() {
  224   		this( new SettingsFactory() );
  225   	}
  226   
  227   	/**
  228   	 * Iterate the entity mappings
  229   	 *
  230   	 * @return Iterator of the entity mappings currently contained in the configuration.
  231   	 */
  232   	public Iterator getClassMappings() {
  233   		return classes.values().iterator();
  234   	}
  235   
  236   	/**
  237   	 * Iterate the collection mappings
  238   	 *
  239   	 * @return Iterator of the collection mappings currently contained in the configuration.
  240   	 */
  241   	public Iterator getCollectionMappings() {
  242   		return collections.values().iterator();
  243   	}
  244   
  245   	/**
  246   	 * Iterate the table mappings
  247   	 *
  248   	 * @return Iterator of the table mappings currently contained in the configuration.
  249   	 */
  250   	public Iterator getTableMappings() {
  251   		return tables.values().iterator();
  252   	}
  253   
  254   	/**
  255   	 * Get the mapping for a particular entity
  256   	 *
  257   	 * @param entityName An entity name.
  258   	 * @return the entity mapping information
  259   	 */
  260   	public PersistentClass getClassMapping(String entityName) {
  261   		return (PersistentClass) classes.get( entityName );
  262   	}
  263   
  264   	/**
  265   	 * Get the mapping for a particular collection role
  266   	 *
  267   	 * @param role a collection role
  268   	 * @return The collection mapping information
  269   	 */
  270   	public Collection getCollectionMapping(String role) {
  271   		return (Collection) collections.get( role );
  272   	}
  273   
  274   	/**
  275   	 * Set a custom entity resolver. This entity resolver must be
  276   	 * set before addXXX(misc) call.
  277   	 * Default value is {@link org.hibernate.util.DTDEntityResolver}
  278   	 *
  279   	 * @param entityResolver entity resolver to use
  280   	 */
  281   	public void setEntityResolver(EntityResolver entityResolver) {
  282   		this.entityResolver = entityResolver;
  283   	}
  284   
  285   	public EntityResolver getEntityResolver() {
  286   		return entityResolver;
  287   	}
  288   
  289   	/**
  290   	 * Retrieve the user-supplied delegate to handle non-existent entity
  291   	 * scenarios.  May be null.
  292   	 *
  293   	 * @return The user-supplied delegate
  294   	 */
  295   	public EntityNotFoundDelegate getEntityNotFoundDelegate() {
  296   		return entityNotFoundDelegate;
  297   	}
  298   
  299   	/**
  300   	 * Specify a user-supplied delegate to be used to handle scenarios where an entity could not be
  301   	 * located by specified id.  This is mainly intended for EJB3 implementations to be able to
  302   	 * control how proxy initialization errors should be handled...
  303   	 *
  304   	 * @param entityNotFoundDelegate The delegate to use
  305   	 */
  306   	public void setEntityNotFoundDelegate(EntityNotFoundDelegate entityNotFoundDelegate) {
  307   		this.entityNotFoundDelegate = entityNotFoundDelegate;
  308   	}
  309   
  310   	/**
  311   	 * Read mappings from a particular XML file
  312   	 *
  313   	 * @param xmlFile a path to a file
  314   	 * @return this (for method chaining purposes)
  315   	 * @throws org.hibernate.MappingException Indicates inability to locate or parse
  316   	 * the specified mapping file.
  317   	 * @see #addFile(java.io.File)
  318   	 */
  319   	public Configuration addFile(String xmlFile) throws MappingException {
  320   		return addFile( new File( xmlFile ) );
  321   	}
  322   
  323   	/**
  324   	 * Read mappings from a particular XML file
  325   	 *
  326   	 * @param xmlFile a path to a file
  327   	 * @return this (for method chaining purposes)
  328   	 * @throws org.hibernate.MappingException Indicates inability to locate or parse
  329   	 * the specified mapping file.
  330   	 */
  331   	public Configuration addFile(File xmlFile) throws MappingException {
  332   		log.info( "Reading mappings from file: " + xmlFile.getPath() );
  333   		if ( !xmlFile.exists() ) {
  334   			throw new MappingNotFoundException( "file", xmlFile.toString() );
  335   		}
  336   		try {
  337   			List errors = new ArrayList();
  338   			org.dom4j.Document doc = xmlHelper.createSAXReader( xmlFile.toString(), errors, entityResolver ).read( xmlFile );
  339   			if ( errors.size() != 0 ) {
  340   				throw new InvalidMappingException( "file", xmlFile.toString(), ( Throwable ) errors.get( 0 ) );
  341   			}
  342   			add( doc );
  343   			return this;
  344   		}
  345   		catch ( InvalidMappingException e ) {
  346   			throw e;
  347   		}
  348   		catch  ( MappingNotFoundException e ) {
  349   			throw e;
  350   		}
  351   		catch ( Exception e ) {
  352   			throw new InvalidMappingException( "file", xmlFile.toString(), e );
  353   		}
  354   	}
  355   
  356   	/**
  357   	 * Add a cached mapping file.  A cached file is a serialized representation
  358   	 * of the DOM structure of a particular mapping.  It is saved from a previous
  359   	 * call as a file with the name <tt>xmlFile + ".bin"</tt> where xmlFile is
  360   	 * the name of the original mapping file.
  361   	 * </p>
  362   	 * If a cached <tt>xmlFile + ".bin"</tt> exists and is newer than
  363   	 * <tt>xmlFile</tt> the <tt>".bin"</tt> file will be read directly. Otherwise
  364   	 * xmlFile is read and then serialized to <tt>xmlFile + ".bin"</tt> for use
  365   	 * the next time.
  366   	 *
  367   	 * @param xmlFile The cacheable mapping file to be added.
  368   	 * @return this (for method chaining purposes)
  369   	 * @throws MappingException Indicates problems reading the cached file or processing
  370   	 * the non-cached file.
  371   	 */
  372   	public Configuration addCacheableFile(File xmlFile) throws MappingException {
  373   		try {
  374   			File cachedFile = new File( xmlFile.getAbsolutePath() + ".bin" );
  375   			org.dom4j.Document doc = null;
  376   
  377   			final boolean useCachedFile = xmlFile.exists() &&
  378   					cachedFile.exists() &&
  379   					xmlFile.lastModified() < cachedFile.lastModified();
  380   
  381   			if ( useCachedFile ) {
  382   				try {
  383   					log.info( "Reading mappings from cache file: " + cachedFile );
  384   					doc = ( org.dom4j.Document ) SerializationHelper.deserialize( new FileInputStream( cachedFile ) );
  385   				}
  386   				catch ( SerializationException e ) {
  387   					log.warn( "Could not deserialize cache file: " + cachedFile.getPath(), e );
  388   				}
  389   				catch ( FileNotFoundException e ) {
  390   					log.warn( "I/O reported cached file could not be found : " + cachedFile.getPath(), e );
  391   				}
  392   			}
  393   
  394   			// if doc is null, then for whatever reason, the cached file cannot be used...
  395   			if ( doc == null ) {
  396   				if ( !xmlFile.exists() ) {
  397   					throw new MappingNotFoundException( "file", xmlFile.toString() );
  398   				}
  399   
  400   				log.info( "Reading mappings from file: " + xmlFile );
  401   				List errors = new ArrayList();
  402   				try {
  403   					doc = xmlHelper.createSAXReader( xmlFile.getAbsolutePath(), errors, entityResolver ).read( xmlFile );
  404   					if ( errors.size() != 0 ) {
  405   						throw new MappingException( "invalid mapping", ( Throwable ) errors.get( 0 ) );
  406   					}
  407   				}
  408   				catch( DocumentException e){
  409   					throw new MappingException( "invalid mapping", e );
  410   				}
  411   
  412   				try {
  413   					log.debug( "Writing cache file for: " + xmlFile + " to: " + cachedFile );
  414   					SerializationHelper.serialize( ( Serializable ) doc, new FileOutputStream( cachedFile ) );
  415   				}
  416   				catch ( SerializationException e ) {
  417   					log.warn( "Could not write cached file: " + cachedFile, e );
  418   				}
  419   				catch ( FileNotFoundException e ) {
  420   					log.warn( "I/O reported error writing cached file : " + cachedFile.getPath(), e );
  421   				}
  422   			}
  423   
  424   			add( doc );
  425   			return this;
  426   
  427   		}
  428   		catch ( InvalidMappingException e ) {
  429   			throw e;
  430   		}
  431   		catch  ( MappingNotFoundException e ) {
  432   			throw e;
  433   		}
  434   		catch ( Exception e ) {
  435   			throw new InvalidMappingException( "file", xmlFile.toString(), e );
  436   		}
  437   	}
  438   
  439   	/**
  440   	 * Add a cacheable mapping file.
  441   	 *
  442   	 * @param xmlFile The name of the file to be added.  This must be in a form
  443   	 * useable to simply construct a {@link java.io.File} instance.
  444   	 * @return this (for method chaining purposes)
  445   	 * @throws MappingException Indicates problems reading the cached file or processing
  446   	 * the non-cached file.
  447   	 * @see #addCacheableFile(java.io.File)
  448   	 */
  449   	public Configuration addCacheableFile(String xmlFile) throws MappingException {
  450   		return addCacheableFile( new File( xmlFile ) );
  451   	}
  452   
  453   
  454   	/**
  455   	 * Read mappings from a <tt>String</tt>
  456   	 *
  457   	 * @param xml an XML string
  458   	 * @return this (for method chaining purposes)
  459   	 * @throws org.hibernate.MappingException Indicates problems parsing the
  460   	 * given XML string
  461   	 */
  462   	public Configuration addXML(String xml) throws MappingException {
  463   		if ( log.isDebugEnabled() ) {
  464   			log.debug( "Mapping XML:\n" + xml );
  465   		}
  466   		try {
  467   			List errors = new ArrayList();
  468   			org.dom4j.Document doc = xmlHelper.createSAXReader( "XML String", errors, entityResolver )
  469   					.read( new StringReader( xml ) );
  470   			if ( errors.size() != 0 ) {
  471   				throw new MappingException( "invalid mapping", (Throwable) errors.get( 0 ) );
  472   			}
  473   			add( doc );
  474   		}
  475   		catch (DocumentException e) {
  476   			throw new MappingException( "Could not parse mapping document in XML string", e );
  477   		}
  478   		return this;
  479   	}
  480   
  481   	/**
  482   	 * Read mappings from a <tt>URL</tt>
  483   	 *
  484   	 * @param url The url for the mapping document to be read.
  485   	 * @return this (for method chaining purposes)
  486   	 * @throws MappingException Indicates problems reading the URL or processing
  487   	 * the mapping document.
  488   	 */
  489   	public Configuration addURL(URL url) throws MappingException {
  490   		if ( log.isDebugEnabled() ) {
  491   			log.debug( "Reading mapping document from URL:" + url.toExternalForm() );
  492   		}
  493   		try {
  494   			addInputStream( url.openStream() );
  495   		}
  496   		catch ( InvalidMappingException e ) {
  497   			throw new InvalidMappingException( "URL", url.toExternalForm(), e.getCause() );
  498   		}
  499   		catch (Exception e) {
  500   			throw new InvalidMappingException( "URL", url.toExternalForm(), e );
  501   		}
  502   		return this;
  503   	}
  504   
  505   	/**
  506   	 * Read mappings from a DOM <tt>Document</tt>
  507   	 *
  508   	 * @param doc The DOM document
  509   	 * @return this (for method chaining purposes)
  510   	 * @throws MappingException Indicates problems reading the DOM or processing
  511   	 * the mapping document.
  512   	 */
  513   	public Configuration addDocument(Document doc) throws MappingException {
  514   		if ( log.isDebugEnabled() ) {
  515   			log.debug( "Mapping document:\n" + doc );
  516   		}
  517   		add( xmlHelper.createDOMReader().read( doc ) );
  518   		return this;
  519   	}
  520   
  521   	/**
  522   	 * Read mappings from an {@link java.io.InputStream}.
  523   	 *
  524   	 * @param xmlInputStream The input stream containing a DOM.
  525   	 * @return this (for method chaining purposes)
  526   	 * @throws MappingException Indicates problems reading the stream, or
  527   	 * processing the contained mapping document.
  528   	 */
  529   	public Configuration addInputStream(InputStream xmlInputStream) throws MappingException {
  530   		try {
  531   			List errors = new ArrayList();
  532   			org.dom4j.Document doc = xmlHelper.createSAXReader( "XML InputStream", errors, entityResolver )
  533   					.read( new InputSource( xmlInputStream ) );
  534   			if ( errors.size() != 0 ) {
  535   				throw new InvalidMappingException( "invalid mapping", null, (Throwable) errors.get( 0 ) );
  536   			}
  537   			add( doc );
  538   			return this;
  539   		}
  540   		catch (DocumentException e) {
  541   			throw new InvalidMappingException( "input stream", null, e );
  542   		}
  543   		finally {
  544   			try {
  545   				xmlInputStream.close();
  546   			}
  547   			catch (IOException ioe) {
  548   				log.warn( "Could not close input stream", ioe );
  549   			}
  550   		}
  551   	}
  552   
  553   	/**
  554   	 * Read mappings as a application resource (i.e. classpath lookup).
  555   	 *
  556   	 * @param resourceName The resource name
  557   	 * @param classLoader The class loader to use.
  558   	 * @return this (for method chaining purposes)
  559   	 * @throws MappingException Indicates problems locating the resource or
  560   	 * processing the contained mapping document.
  561   	 */
  562   	public Configuration addResource(String resourceName, ClassLoader classLoader) throws MappingException {
  563   		log.info( "Reading mappings from resource: " + resourceName );
  564   		InputStream rsrc = classLoader.getResourceAsStream( resourceName );
  565   		if ( rsrc == null ) {
  566   			throw new MappingNotFoundException( "resource", resourceName );
  567   		}
  568   		try {
  569   			return addInputStream( rsrc );
  570   		}
  571   		catch (MappingException me) {
  572   			throw new InvalidMappingException( "resource", resourceName, me );
  573   		}
  574   	}
  575   
  576   	/**
  577   	 * Read mappings as a application resourceName (i.e. classpath lookup)
  578   	 * trying different classloaders.
  579   	 *
  580   	 * @param resourceName The resource name
  581   	 * @return this (for method chaining purposes)
  582   	 * @throws MappingException Indicates problems locating the resource or
  583   	 * processing the contained mapping document.
  584   	 */
  585   	public Configuration addResource(String resourceName) throws MappingException {
  586   		log.info( "Reading mappings from resource : " + resourceName );
  587   		ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
  588   		InputStream rsrc = null;
  589   		if (contextClassLoader!=null) {
  590   			rsrc = contextClassLoader.getResourceAsStream( resourceName );
  591   		}
  592   		if ( rsrc == null ) {
  593   			rsrc = Environment.class.getClassLoader().getResourceAsStream( resourceName );
  594   		}
  595   		if ( rsrc == null ) {
  596   			throw new MappingNotFoundException( "resource", resourceName );
  597   		}
  598   		try {
  599   			return addInputStream( rsrc );
  600   		}
  601   		catch (MappingException me) {
  602   			throw new InvalidMappingException( "resource", resourceName, me );
  603   		}
  604   	}
  605   
  606   	/**
  607   	 * Read a mapping as an application resouurce using the convention that a class
  608   	 * named <tt>foo.bar.Foo</tt> is mapped by a file <tt>foo/bar/Foo.hbm.xml</tt>
  609   	 * which can be resolved as a classpath resource.
  610   	 *
  611   	 * @param persistentClass The mapped class
  612   	 * @return this (for method chaining purposes)
  613   	 * @throws MappingException Indicates problems locating the resource or
  614   	 * processing the contained mapping document.
  615   	 */
  616   	public Configuration addClass(Class persistentClass) throws MappingException {
  617   		String mappingResourceName = persistentClass.getName().replace( '.', '/' ) + ".hbm.xml";
  618   		log.info( "Reading mappings from resource: " + mappingResourceName );
  619   		return addResource( mappingResourceName, persistentClass.getClassLoader() );
  620   	}
  621   
  622   	/**
  623   	 * Read all mappings from a jar file
  624   	 * <p/>
  625   	 * Assumes that any file named <tt>*.hbm.xml</tt> is a mapping document.
  626   	 *
  627   	 * @param jar a jar file
  628   	 * @return this (for method chaining purposes)
  629   	 * @throws MappingException Indicates problems reading the jar file or
  630   	 * processing the contained mapping documents.
  631   	 */
  632   	public Configuration addJar(File jar) throws MappingException {
  633   		log.info( "Searching for mapping documents in jar: " + jar.getName() );
  634   		JarFile jarFile = null;
  635   		try {
  636   			try {
  637   				jarFile = new JarFile( jar );
  638   			}
  639   			catch (IOException ioe) {
  640   				throw new InvalidMappingException(
  641   						"Could not read mapping documents from jar: " + jar.getName(), "jar", jar.getName(),
  642   						ioe
  643   				);
  644   			}
  645   			Enumeration jarEntries = jarFile.entries();
  646   			while ( jarEntries.hasMoreElements() ) {
  647   				ZipEntry ze = (ZipEntry) jarEntries.nextElement();
  648   				if ( ze.getName().endsWith( ".hbm.xml" ) ) {
  649   					log.info( "Found mapping document in jar: " + ze.getName() );
  650   					try {
  651   						addInputStream( jarFile.getInputStream( ze ) );
  652   					}
  653   					catch (Exception e) {
  654   						throw new InvalidMappingException(
  655   								"Could not read mapping documents from jar: " + jar.getName(),
  656   								"jar",
  657   								jar.getName(),
  658   								e
  659   						);
  660   					}
  661   				}
  662   			}
  663   		}
  664   		finally {
  665   			try {
  666   				if ( jarFile != null ) {
  667   					jarFile.close();
  668   				}
  669   			}
  670   			catch (IOException ioe) {
  671   				log.error("could not close jar", ioe);
  672   			}
  673   		}
  674   
  675   		return this;
  676   	}
  677   
  678   	/**
  679   	 * Read all mapping documents from a directory tree.
  680   	 * <p/>
  681   	 * Assumes that any file named <tt>*.hbm.xml</tt> is a mapping document.
  682   	 *
  683   	 * @param dir The directory
  684   	 * @return this (for method chaining purposes)
  685   	 * @throws MappingException Indicates problems reading the jar file or
  686   	 * processing the contained mapping documents.
  687   	 */
  688   	public Configuration addDirectory(File dir) throws MappingException {
  689   		File[] files = dir.listFiles();
  690   		for ( int i = 0; i < files.length ; i++ ) {
  691   			if ( files[i].isDirectory() ) {
  692   				addDirectory( files[i] );
  693   			}
  694   			else if ( files[i].getName().endsWith( ".hbm.xml" ) ) {
  695   				addFile( files[i] );
  696   			}
  697   		}
  698   		return this;
  699   	}
  700   
  701   	protected void add(org.dom4j.Document doc) throws MappingException {
  702   		HbmBinder.bindRoot( doc, createMappings(), CollectionHelper.EMPTY_MAP );
  703   	}
  704   
  705   	/**
  706   	 * Create a new <tt>Mappings</tt> to add class and collection
  707   	 * mappings to.
  708   	 */
  709   	public Mappings createMappings() {
  710   		return new Mappings(
  711   				classes,
  712   				collections,
  713   				tables,
  714   				namedQueries,
  715   				namedSqlQueries,
  716   				sqlResultSetMappings,
  717   				imports,
  718   				secondPasses,
  719   				propertyReferences,
  720   				namingStrategy,
  721   				typeDefs,
  722   				filterDefinitions,
  723   				extendsQueue,
  724   				auxiliaryDatabaseObjects,
  725   				tableNameBinding,
  726   				columnNameBindingPerTable
  727   			);
  728   	}
  729   
  730   
  731   	private Iterator iterateGenerators(Dialect dialect) throws MappingException {
  732   
  733   		TreeMap generators = new TreeMap();
  734   		String defaultCatalog = properties.getProperty( Environment.DEFAULT_CATALOG );
  735   		String defaultSchema = properties.getProperty( Environment.DEFAULT_SCHEMA );
  736   
  737   		Iterator iter = classes.values().iterator();
  738   		while ( iter.hasNext() ) {
  739   			PersistentClass pc = (PersistentClass) iter.next();
  740   
  741   			if ( !pc.isInherited() ) {
  742   
  743   				IdentifierGenerator ig = pc.getIdentifier()
  744   						.createIdentifierGenerator(
  745   								dialect,
  746   								defaultCatalog,
  747   								defaultSchema,
  748   								(RootClass) pc
  749   							);
  750   
  751   				if ( ig instanceof PersistentIdentifierGenerator ) {
  752   					generators.put( ( (PersistentIdentifierGenerator) ig ).generatorKey(), ig );
  753   				}
  754   
  755   			}
  756   		}
  757   
  758   		iter = collections.values().iterator();
  759   		while ( iter.hasNext() ) {
  760   			Collection collection = (Collection) iter.next();
  761   
  762   			if ( collection.isIdentified() ) {
  763   
  764   				IdentifierGenerator ig = ( (IdentifierCollection) collection ).getIdentifier()
  765   						.createIdentifierGenerator(
  766   								dialect,
  767   								defaultCatalog,
  768   								defaultSchema,
  769   								null
  770   							);
  771   
  772   				if ( ig instanceof PersistentIdentifierGenerator ) {
  773   					generators.put( ( (PersistentIdentifierGenerator) ig ).generatorKey(), ig );
  774   				}
  775   
  776   			}
  777   		}
  778   
  779   		return generators.values().iterator();
  780   	}
  781   
  782   	/**
  783   	 * Generate DDL for dropping tables
  784   	 *
  785   	 * @see org.hibernate.tool.hbm2ddl.SchemaExport
  786   	 */
  787   	public String[] generateDropSchemaScript(Dialect dialect) throws HibernateException {
  788   
  789   		secondPassCompile();
  790   
  791   		String defaultCatalog = properties.getProperty( Environment.DEFAULT_CATALOG );
  792   		String defaultSchema = properties.getProperty( Environment.DEFAULT_SCHEMA );
  793   
  794   		ArrayList script = new ArrayList( 50 );
  795   
  796   		// drop them in reverse order in case db needs it done that way...
  797   		ListIterator itr = auxiliaryDatabaseObjects.listIterator( auxiliaryDatabaseObjects.size() );
  798   		while ( itr.hasPrevious() ) {
  799   			AuxiliaryDatabaseObject object = (AuxiliaryDatabaseObject) itr.previous();
  800   			if ( object.appliesToDialect( dialect ) ) {
  801   				script.add( object.sqlDropString( dialect, defaultCatalog, defaultSchema ) );
  802   			}
  803   		}
  804   
  805   		if ( dialect.dropConstraints() ) {
  806   			Iterator iter = getTableMappings();
  807   			while ( iter.hasNext() ) {
  808   				Table table = (Table) iter.next();
  809   				if ( table.isPhysicalTable() ) {
  810   					Iterator subIter = table.getForeignKeyIterator();
  811   					while ( subIter.hasNext() ) {
  812   						ForeignKey fk = (ForeignKey) subIter.next();
  813   						if ( fk.isPhysicalConstraint() ) {
  814   							script.add(
  815   									fk.sqlDropString(
  816   											dialect,
  817   											defaultCatalog,
  818   											defaultSchema
  819   										)
  820   								);
  821   						}
  822   					}
  823   				}
  824   			}
  825   		}
  826   
  827   
  828   		Iterator iter = getTableMappings();
  829   		while ( iter.hasNext() ) {
  830   
  831   			Table table = (Table) iter.next();
  832   			if ( table.isPhysicalTable() ) {
  833   
  834   				/*Iterator subIter = table.getIndexIterator();
  835   				while ( subIter.hasNext() ) {
  836   					Index index = (Index) subIter.next();
  837   					if ( !index.isForeignKey() || !dialect.hasImplicitIndexForForeignKey() ) {
  838   						script.add( index.sqlDropString(dialect) );
  839   					}
  840   				}*/
  841   
  842   				script.add(
  843   						table.sqlDropString(
  844   								dialect,
  845   								defaultCatalog,
  846   								defaultSchema
  847   							)
  848   					);
  849   
  850   			}
  851   
  852   		}
  853   
  854   		iter = iterateGenerators( dialect );
  855   		while ( iter.hasNext() ) {
  856   			String[] lines = ( (PersistentIdentifierGenerator) iter.next() ).sqlDropStrings( dialect );
  857   			for ( int i = 0; i < lines.length ; i++ ) {
  858   				script.add( lines[i] );
  859   			}
  860   		}
  861   
  862   		return ArrayHelper.toStringArray( script );
  863   	}
  864   
  865   	/**
  866   	 * Generate DDL for creating tables
  867   	 *
  868   	 * @see org.hibernate.tool.hbm2ddl.SchemaExport
  869   	 */
  870   	public String[] generateSchemaCreationScript(Dialect dialect) throws HibernateException {
  871   		secondPassCompile();
  872   
  873   		ArrayList script = new ArrayList( 50 );
  874   		String defaultCatalog = properties.getProperty( Environment.DEFAULT_CATALOG );
  875   		String defaultSchema = properties.getProperty( Environment.DEFAULT_SCHEMA );
  876   
  877   		Iterator iter = getTableMappings();
  878   		while ( iter.hasNext() ) {
  879   			Table table = (Table) iter.next();
  880   			if ( table.isPhysicalTable() ) {
  881   				script.add(
  882   						table.sqlCreateString(
  883   								dialect,
  884   								mapping,
  885   								defaultCatalog,
  886   								defaultSchema
  887   							)
  888   					);
  889   				Iterator comments = table.sqlCommentStrings( dialect, defaultCatalog, defaultSchema );
  890   				while ( comments.hasNext() ) {
  891   					script.add( comments.next() );
  892   				}
  893   			}
  894   		}
  895   
  896   		iter = getTableMappings();
  897   		while ( iter.hasNext() ) {
  898   			Table table = (Table) iter.next();
  899   			if ( table.isPhysicalTable() ) {
  900   
  901   				if ( !dialect.supportsUniqueConstraintInCreateAlterTable() ) {
  902   					Iterator subIter = table.getUniqueKeyIterator();
  903   					while ( subIter.hasNext() ) {
  904   						UniqueKey uk = (UniqueKey) subIter.next();
  905   						String constraintString = uk.sqlCreateString( dialect, mapping, defaultCatalog, defaultSchema );
  906   						if (constraintString != null) script.add( constraintString );
  907   					}
  908   				}
  909   
  910   
  911   				Iterator subIter = table.getIndexIterator();
  912   				while ( subIter.hasNext() ) {
  913   					Index index = (Index) subIter.next();
  914   					script.add(
  915   							index.sqlCreateString(
  916   									dialect,
  917   									mapping,
  918   									defaultCatalog,
  919   									defaultSchema
  920   								)
  921   						);
  922   				}
  923   
  924   				if ( dialect.hasAlterTable() ) {
  925   					subIter = table.getForeignKeyIterator();
  926   					while ( subIter.hasNext() ) {
  927   						ForeignKey fk = (ForeignKey) subIter.next();
  928   						if ( fk.isPhysicalConstraint() ) {
  929   							script.add(
  930   									fk.sqlCreateString(
  931   											dialect, mapping,
  932   											defaultCatalog,
  933   											defaultSchema
  934   										)
  935   								);
  936   						}
  937   					}
  938   				}
  939   
  940   			}
  941   		}
  942   
  943   		iter = iterateGenerators( dialect );
  944   		while ( iter.hasNext() ) {
  945   			String[] lines = ( (PersistentIdentifierGenerator) iter.next() ).sqlCreateStrings( dialect );
  946   			for ( int i = 0; i < lines.length ; i++ ) {
  947   				script.add( lines[i] );
  948   			}
  949   		}
  950   
  951   		Iterator itr = auxiliaryDatabaseObjects.iterator();
  952   		while ( itr.hasNext() ) {
  953   			AuxiliaryDatabaseObject object = (AuxiliaryDatabaseObject) itr.next();
  954   			if ( object.appliesToDialect( dialect ) ) {
  955   				script.add( object.sqlCreateString( dialect, mapping, defaultCatalog, defaultSchema ) );
  956   			}
  957   		}
  958   
  959   		return ArrayHelper.toStringArray( script );
  960   	}
  961   
  962   	/**
  963   	 * Generate DDL for altering tables
  964   	 *
  965   	 * @see org.hibernate.tool.hbm2ddl.SchemaUpdate
  966   	 */
  967   	public String[] generateSchemaUpdateScript(Dialect dialect, DatabaseMetadata databaseMetadata)
  968   			throws HibernateException {
  969   		secondPassCompile();
  970   
  971   		String defaultCatalog = properties.getProperty( Environment.DEFAULT_CATALOG );
  972   		String defaultSchema = properties.getProperty( Environment.DEFAULT_SCHEMA );
  973   
  974   		ArrayList script = new ArrayList( 50 );
  975   
  976   		Iterator iter = getTableMappings();
  977   		while ( iter.hasNext() ) {
  978   			Table table = (Table) iter.next();
  979   			if ( table.isPhysicalTable() ) {
  980   				
  981   				TableMetadata tableInfo = databaseMetadata.getTableMetadata(
  982   						table.getName(),
  983   						( table.getSchema() == null ) ? defaultSchema : table.getSchema(),
  984   						( table.getCatalog() == null ) ? defaultCatalog : table.getCatalog(),
  985   								table.isQuoted()
  986   
  987   					);
  988   				if ( tableInfo == null ) {
  989   					script.add(
  990   							table.sqlCreateString(
  991   									dialect,
  992   									mapping,
  993   									defaultCatalog,
  994   									defaultSchema
  995   								)
  996   						);
  997   				}
  998   				else {
  999   					Iterator subiter = table.sqlAlterStrings(
 1000   							dialect,
 1001   							mapping,
 1002   							tableInfo,
 1003   							defaultCatalog,
 1004   							defaultSchema
 1005   						);
 1006   					while ( subiter.hasNext() ) {
 1007   						script.add( subiter.next() );
 1008   					}
 1009   				}
 1010   
 1011   				Iterator comments = table.sqlCommentStrings( dialect, defaultCatalog, defaultSchema );
 1012   				while ( comments.hasNext() ) {
 1013   					script.add( comments.next() );
 1014   				}
 1015   
 1016   			}
 1017   		}
 1018   
 1019   		iter = getTableMappings();
 1020   		while ( iter.hasNext() ) {
 1021   			Table table = (Table) iter.next();
 1022   			if ( table.isPhysicalTable() ) {
 1023   
 1024   				TableMetadata tableInfo = databaseMetadata.getTableMetadata(
 1025   						table.getName(),
 1026   						table.getSchema(),
 1027   						table.getCatalog(),
 1028   						table.isQuoted()
 1029   					);
 1030   
 1031   				if ( dialect.hasAlterTable() ) {
 1032   					Iterator subIter = table.getForeignKeyIterator();
 1033   					while ( subIter.hasNext() ) {
 1034   						ForeignKey fk = (ForeignKey) subIter.next();
 1035   						if ( fk.isPhysicalConstraint() ) {
 1036   							boolean create = tableInfo == null || (
 1037   									tableInfo.getForeignKeyMetadata( fk.getName() ) == null && (
 1038   											//Icky workaround for MySQL bug:
 1039   											!( dialect instanceof MySQLDialect ) ||
 1040   													tableInfo.getIndexMetadata( fk.getName() ) == null
 1041   										)
 1042   								);
 1043   							if ( create ) {
 1044   								script.add(
 1045   										fk.sqlCreateString(
 1046   												dialect,
 1047   												mapping,
 1048   												defaultCatalog,
 1049   												defaultSchema
 1050   											)
 1051   									);
 1052   							}
 1053   						}
 1054   					}
 1055   				}
 1056   
 1057   			}
 1058   
 1059   			/*//broken, 'cos we don't generate these with names in SchemaExport
 1060   			subIter = table.getIndexIterator();
 1061   			while ( subIter.hasNext() ) {
 1062   				Index index = (Index) subIter.next();
 1063   				if ( !index.isForeignKey() || !dialect.hasImplicitIndexForForeignKey() ) {
 1064   					if ( tableInfo==null || tableInfo.getIndexMetadata( index.getFilterName() ) == null ) {
 1065   						script.add( index.sqlCreateString(dialect, mapping) );
 1066   					}
 1067   				}
 1068   			}
 1069   			//broken, 'cos we don't generate these with names in SchemaExport
 1070   			subIter = table.getUniqueKeyIterator();
 1071   			while ( subIter.hasNext() ) {
 1072   				UniqueKey uk = (UniqueKey) subIter.next();
 1073   				if ( tableInfo==null || tableInfo.getIndexMetadata( uk.getFilterName() ) == null ) {
 1074   					script.add( uk.sqlCreateString(dialect, mapping) );
 1075   				}
 1076   			}*/
 1077   		}
 1078   
 1079   		iter = iterateGenerators( dialect );
 1080   		while ( iter.hasNext() ) {
 1081   			PersistentIdentifierGenerator generator = (PersistentIdentifierGenerator) iter.next();
 1082   			Object key = generator.generatorKey();
 1083   			if ( !databaseMetadata.isSequence( key ) && !databaseMetadata.isTable( key ) ) {
 1084   				String[] lines = generator.sqlCreateStrings( dialect );
 1085   				for ( int i = 0; i < lines.length ; i++ ) {
 1086   					script.add( lines[i] );
 1087   				}
 1088   			}
 1089   		}
 1090   
 1091   		return ArrayHelper.toStringArray( script );
 1092   	}
 1093   
 1094   	public void validateSchema(Dialect dialect, DatabaseMetadata databaseMetadata)
 1095   			throws HibernateException {
 1096   		secondPassCompile();
 1097   
 1098   		String defaultCatalog = properties.getProperty( Environment.DEFAULT_CATALOG );
 1099   		String defaultSchema = properties.getProperty( Environment.DEFAULT_SCHEMA );
 1100   		
 1101   		Iterator iter = getTableMappings();
 1102   		while ( iter.hasNext() ) {
 1103   			Table table = (Table) iter.next();
 1104   			if ( table.isPhysicalTable() ) {
 1105   				
 1106   
 1107   				TableMetadata tableInfo = databaseMetadata.getTableMetadata(
 1108   						table.getName(),
 1109   						( table.getSchema() == null ) ? defaultSchema : table.getSchema(),
 1110   						( table.getCatalog() == null ) ? defaultCatalog : table.getCatalog(),
 1111   								table.isQuoted());
 1112   				if ( tableInfo == null ) {
 1113   					throw new HibernateException( "Missing table: " + table.getName() );
 1114   				}
 1115   				else {
 1116   					table.validateColumns( dialect, mapping, tableInfo );
 1117   				}
 1118   
 1119   			}
 1120   		}
 1121   
 1122   		iter = iterateGenerators( dialect );
 1123   		while ( iter.hasNext() ) {
 1124   			PersistentIdentifierGenerator generator = (PersistentIdentifierGenerator) iter.next();
 1125   			Object key = generator.generatorKey();
 1126   			if ( !databaseMetadata.isSequence( key ) && !databaseMetadata.isTable( key ) ) {
 1127   				throw new HibernateException( "Missing sequence or table: " + key );
 1128   			}
 1129   		}
 1130   	}
 1131   
 1132   	private void validate() throws MappingException {
 1133   		Iterator iter = classes.values().iterator();
 1134   		while ( iter.hasNext() ) {
 1135   			( (PersistentClass) iter.next() ).validate( mapping );
 1136   		}
 1137   		iter = collections.values().iterator();
 1138   		while ( iter.hasNext() ) {
 1139   			( (Collection) iter.next() ).validate( mapping );
 1140   		}
 1141   	}
 1142   
 1143   	/**
 1144   	 * Call this to ensure the mappings are fully compiled/built. Usefull to ensure getting
 1145   	 * access to all information in the metamodel when calling e.g. getClassMappings().
 1146   	 */
 1147   	public void buildMappings() {
 1148   		secondPassCompile();
 1149   	}
 1150   
 1151   	// This method may be called many times!!
 1152   	protected void secondPassCompile() throws MappingException {
 1153   		log.debug( "processing extends queue" );
 1154   
 1155   		processExtendsQueue();
 1156   
 1157   		log.debug( "processing collection mappings" );
 1158   
 1159   		Iterator iter = secondPasses.iterator();
 1160   		while ( iter.hasNext() ) {
 1161   			SecondPass sp = (SecondPass) iter.next();
 1162   			if ( ! (sp instanceof QuerySecondPass) ) {
 1163   				sp.doSecondPass( classes );
 1164   				iter.remove();
 1165   			}
 1166   		}
 1167   
 1168   		log.debug( "processing native query and ResultSetMapping mappings" );
 1169   		iter = secondPasses.iterator();
 1170   		while ( iter.hasNext() ) {
 1171   			SecondPass sp = (SecondPass) iter.next();
 1172   			sp.doSecondPass( classes );
 1173   			iter.remove();
 1174   		}
 1175   
 1176   		log.debug( "processing association property references" );
 1177   
 1178   		iter = propertyReferences.iterator();
 1179   		while ( iter.hasNext() ) {
 1180   			Mappings.PropertyReference upr = (Mappings.PropertyReference) iter.next();
 1181   
 1182   			PersistentClass clazz = getClassMapping( upr.referencedClass );
 1183   			if ( clazz == null ) {
 1184   				throw new MappingException(
 1185   						"property-ref to unmapped class: " +
 1186   						upr.referencedClass
 1187   					);
 1188   			}
 1189   
 1190   			Property prop = clazz.getReferencedProperty( upr.propertyName );
 1191   			if ( upr.unique ) {
 1192   				( (SimpleValue) prop.getValue() ).setAlternateUniqueKey( true );
 1193   			}
 1194   		}
 1195   
 1196   		//TODO: Somehow add the newly created foreign keys to the internal collection
 1197   
 1198   		log.debug( "processing foreign key constraints" );
 1199   
 1200   		iter = getTableMappings();
 1201   		Set done = new HashSet();
 1202   		while ( iter.hasNext() ) {
 1203   			secondPassCompileForeignKeys( (Table) iter.next(), done );
 1204   		}
 1205   
 1206   	}
 1207   
 1208   	/**
 1209   	 * Try to empty the extends queue.
 1210   	 */
 1211   	private void processExtendsQueue() {
 1212   		// todo : would love to have this work on a notification basis
 1213   		//    where the successful binding of an entity/subclass would
 1214   		//    emit a notification which the extendsQueue entries could
 1215   		//    react to...
 1216   		org.dom4j.Document document = findPossibleExtends();
 1217   		while ( document != null ) {
 1218   			add( document );
 1219   			document = findPossibleExtends();
 1220   		}
 1221   
 1222   		if ( extendsQueue.size() > 0 ) {
 1223   //			Iterator iterator = extendsQueue.iterator();
 1224   			Iterator iterator = extendsQueue.keySet().iterator();
 1225   			StringBuffer buf = new StringBuffer( "Following superclasses referenced in extends not found: " );
 1226   			while ( iterator.hasNext() ) {
 1227   				final ExtendsQueueEntry entry = ( ExtendsQueueEntry ) iterator.next();
 1228   				buf.append( entry.getExplicitName() );
 1229   				if ( entry.getMappingPackage() != null ) {
 1230   					buf.append( "[" ).append( entry.getMappingPackage() ).append( "]" );
 1231   				}
 1232   				if ( iterator.hasNext() ) {
 1233   					buf.append( "," );
 1234   				}
 1235   			}
 1236   			throw new MappingException( buf.toString() );
 1237   		}
 1238   	}
 1239   
 1240   	/**
 1241   	 * Find the first possible element in the queue of extends.
 1242   	 */
 1243   	protected org.dom4j.Document findPossibleExtends() {
 1244   //		Iterator iter = extendsQueue.iterator();
 1245   		Iterator iter = extendsQueue.keySet().iterator();
 1246   		while ( iter.hasNext() ) {
 1247   			final ExtendsQueueEntry entry = ( ExtendsQueueEntry ) iter.next();
 1248   			if ( getClassMapping( entry.getExplicitName() ) != null ) {
 1249   				// found
 1250   				iter.remove();
 1251   				return entry.getDocument();
 1252   			}
 1253   			else if ( getClassMapping( HbmBinder.getClassName( entry.getExplicitName(), entry.getMappingPackage() ) ) != null ) {
 1254   				// found
 1255   				iter.remove();
 1256   				return entry.getDocument();
 1257   			}
 1258   		}
 1259   		return null;
 1260   	}
 1261   
 1262   	protected void secondPassCompileForeignKeys(Table table, Set done) throws MappingException {
 1263   
 1264   		table.createForeignKeys();
 1265   
 1266   		Iterator iter = table.getForeignKeyIterator();
 1267   		while ( iter.hasNext() ) {
 1268   
 1269   			ForeignKey fk = (ForeignKey) iter.next();
 1270   			if ( !done.contains( fk ) ) {
 1271   				done.add( fk );
 1272   				final String referencedEntityName = fk.getReferencedEntityName();
 1273   				if ( referencedEntityName == null ) {
 1274   					throw new MappingException(
 1275   							"An association from the table " +
 1276   							fk.getTable().getName() +
 1277   							" does not specify the referenced entity"
 1278   						);
 1279   				}
 1280   				if ( log.isDebugEnabled() ) {
 1281   					log.debug( "resolving reference to class: " + referencedEntityName );
 1282   				}
 1283   				PersistentClass referencedClass = (PersistentClass) classes.get( referencedEntityName );
 1284   				if ( referencedClass == null ) {
 1285   					throw new MappingException(
 1286   							"An association from the table " +
 1287   							fk.getTable().getName() +
 1288   							" refers to an unmapped class: " +
 1289   							referencedEntityName
 1290   						);
 1291   				}
 1292   				if ( referencedClass.isJoinedSubclass() ) {
 1293   					secondPassCompileForeignKeys( referencedClass.getSuperclass().getTable(), done );
 1294   				}
 1295   				fk.setReferencedTable( referencedClass.getTable() );
 1296   				fk.alignColumns();
 1297   			}
 1298   		}
 1299   	}
 1300   
 1301   	/**
 1302   	 * Get the named queries
 1303   	 */
 1304   	public Map getNamedQueries() {
 1305   		return namedQueries;
 1306   	}
 1307   
 1308   	/**
 1309   	 * Instantiate a new <tt>SessionFactory</tt>, using the properties and
 1310   	 * mappings in this configuration. The <tt>SessionFactory</tt> will be
 1311   	 * immutable, so changes made to the <tt>Configuration</tt> after
 1312   	 * building the <tt>SessionFactory</tt> will not affect it.
 1313   	 *
 1314   	 * @return a new factory for <tt>Session</tt>s
 1315   	 * @see org.hibernate.SessionFactory
 1316   	 */
 1317   	public SessionFactory buildSessionFactory() throws HibernateException {
 1318   		log.debug( "Preparing to build session factory with filters : " + filterDefinitions );
 1319   		secondPassCompile();
 1320   		validate();
 1321   		Environment.verifyProperties( properties );
 1322   		Properties copy = new Properties();
 1323   		copy.putAll( properties );
 1324   		PropertiesHelper.resolvePlaceHolders( copy );
 1325   		Settings settings = buildSettings( copy );
 1326   
 1327   		return new SessionFactoryImpl(
 1328   				this,
 1329   				mapping,
 1330   				settings,
 1331   				getInitializedEventListeners(),
 1332   				sessionFactoryObserver
 1333   			);
 1334   	}
 1335   
 1336   	private EventListeners getInitializedEventListeners() {
 1337   		EventListeners result = (EventListeners) eventListeners.shallowCopy();
 1338   		result.initializeListeners( this );
 1339   		return result;
 1340   	}
 1341   
 1342   	/**
 1343   	 * Return the configured <tt>Interceptor</tt>
 1344   	 */
 1345   	public Interceptor getInterceptor() {
 1346   		return interceptor;
 1347   	}
 1348   
 1349   	/**
 1350   	 * Get all properties
 1351   	 */
 1352   	public Properties getProperties() {
 1353   		return properties;
 1354   	}
 1355   
 1356   	/**
 1357   	 * Configure an <tt>Interceptor</tt>
 1358   	 */
 1359   	public Configuration setInterceptor(Interceptor interceptor) {
 1360   		this.interceptor = interceptor;
 1361   		return this;
 1362   	}
 1363   
 1364   	/**
 1365   	 * Specify a completely new set of properties
 1366   	 */
 1367   	public Configuration setProperties(Properties properties) {
 1368   		this.properties = properties;
 1369   		return this;
 1370   	}
 1371   
 1372   	/**
 1373   	 * Set the given properties
 1374   	 */
 1375   	public Configuration addProperties(Properties extraProperties) {
 1376   		this.properties.putAll( extraProperties );
 1377   		return this;
 1378   	}
 1379   
 1380   	/**
 1381   	 * Adds the incoming properties to the internap properties structure,
 1382   	 * as long as the internal structure does not already contain an
 1383   	 * entry for the given key.
 1384   	 *
 1385   	 * @param properties
 1386   	 * @return this
 1387   	 */
 1388   	public Configuration mergeProperties(Properties properties) {
 1389   		Iterator itr = properties.entrySet().iterator();
 1390   		while ( itr.hasNext() ) {
 1391   			final Map.Entry entry = ( Map.Entry ) itr.next();
 1392   			if ( this.properties.containsKey( entry.getKey() ) ) {
 1393   				continue;
 1394   			}
 1395   			this.properties.setProperty( ( String ) entry.getKey(), ( String ) entry.getValue() );
 1396   		}
 1397   		return this;
 1398   	}
 1399   
 1400   	/**
 1401   	 * Set a property
 1402   	 */
 1403   	public Configuration setProperty(String propertyName, String value) {
 1404   		properties.setProperty( propertyName, value );
 1405   		return this;
 1406   	}
 1407   
 1408   	/**
 1409   	 * Get a property
 1410   	 */
 1411   	public String getProperty(String propertyName) {
 1412   		return properties.getProperty( propertyName );
 1413   	}
 1414   
 1415   	private void addProperties(Element parent) {
 1416   		Iterator iter = parent.elementIterator( "property" );
 1417   		while ( iter.hasNext() ) {
 1418   			Element node = (Element) iter.next();
 1419   			String name = node.attributeValue( "name" );
 1420   			String value = node.getText().trim();
 1421   			log.debug( name + "=" + value );
 1422   			properties.setProperty( name, value );
 1423   			if ( !name.startsWith( "hibernate" ) ) {
 1424   				properties.setProperty( "hibernate." + name, value );
 1425   			}
 1426   		}
 1427   		Environment.verifyProperties( properties );
 1428   	}
 1429   
 1430   	/**
 1431   	 * Get the configuration file as an <tt>InputStream</tt>. Might be overridden
 1432   	 * by subclasses to allow the configuration to be located by some arbitrary
 1433   	 * mechanism.
 1434   	 */
 1435   	protected InputStream getConfigurationInputStream(String resource) throws HibernateException {
 1436   
 1437   		log.info( "Configuration resource: " + resource );
 1438   
 1439   		return ConfigHelper.getResourceAsStream( resource );
 1440   
 1441   	}
 1442   
 1443   	/**
 1444   	 * Use the mappings and properties specified in an application
 1445   	 * resource named <tt>hibernate.cfg.xml</tt>.
 1446   	 */
 1447   	public Configuration configure() throws HibernateException {
 1448   		configure( "/hibernate.cfg.xml" );
 1449   		return this;
 1450   	}
 1451   
 1452   	/**
 1453   	 * Use the mappings and properties specified in the given application
 1454   	 * resource. The format of the resource is defined in
 1455   	 * <tt>hibernate-configuration-3.0.dtd</tt>.
 1456   	 * <p/>
 1457   	 * The resource is found via <tt>getConfigurationInputStream(resource)</tt>.
 1458   	 */
 1459   	public Configuration configure(String resource) throws HibernateException {
 1460   		log.info( "configuring from resource: " + resource );
 1461   		InputStream stream = getConfigurationInputStream( resource );
 1462   		return doConfigure( stream, resource );
 1463   	}
 1464   
 1465   	/**
 1466   	 * Use the mappings and properties specified in the given document.
 1467   	 * The format of the document is defined in
 1468   	 * <tt>hibernate-configuration-3.0.dtd</tt>.
 1469   	 *
 1470   	 * @param url URL from which you wish to load the configuration
 1471   	 * @return A configuration configured via the file
 1472   	 * @throws HibernateException
 1473   	 */
 1474   	public Configuration configure(URL url) throws HibernateException {
 1475   		log.info( "configuring from url: " + url.toString() );
 1476   		try {
 1477   			return doConfigure( url.openStream(), url.toString() );
 1478   		}
 1479   		catch (IOException ioe) {
 1480   			throw new HibernateException( "could not configure from URL: " + url, ioe );
 1481   		}
 1482   	}
 1483   
 1484   	/**
 1485   	 * Use the mappings and properties specified in the given application
 1486   	 * file. The format of the file is defined in
 1487   	 * <tt>hibernate-configuration-3.0.dtd</tt>.
 1488   	 *
 1489   	 * @param configFile <tt>File</tt> from which you wish to load the configuration
 1490   	 * @return A configuration configured via the file
 1491   	 * @throws HibernateException
 1492   	 */
 1493   	public Configuration configure(File configFile) throws HibernateException {
 1494   		log.info( "configuring from file: " + configFile.getName() );
 1495   		try {
 1496   			return doConfigure( new FileInputStream( configFile ), configFile.toString() );
 1497   		}
 1498   		catch (FileNotFoundException fnfe) {
 1499   			throw new HibernateException( "could not find file: " + configFile, fnfe );
 1500   		}
 1501   	}
 1502   
 1503   	/**
 1504   	 * Use the mappings and properties specified in the given application
 1505   	 * resource. The format of the resource is defined in
 1506   	 * <tt>hibernate-configuration-3.0.dtd</tt>.
 1507   	 *
 1508   	 * @param stream	   Inputstream to be read from
 1509   	 * @param resourceName The name to use in warning/error messages
 1510   	 * @return A configuration configured via the stream
 1511   	 * @throws HibernateException
 1512   	 */
 1513   	protected Configuration doConfigure(InputStream stream, String resourceName) throws HibernateException {
 1514   
 1515   		org.dom4j.Document doc;
 1516   		try {
 1517   			List errors = new ArrayList();
 1518   			doc = xmlHelper.createSAXReader( resourceName, errors, entityResolver )
 1519   					.read( new InputSource( stream ) );
 1520   			if ( errors.size() != 0 ) {
 1521   				throw new MappingException(
 1522   						"invalid configuration",
 1523   						(Throwable) errors.get( 0 )
 1524   					);
 1525   			}
 1526   		}
 1527   		catch (DocumentException e) {
 1528   			throw new HibernateException(
 1529   					"Could not parse configuration: " + resourceName,
 1530   					e
 1531   				);
 1532   		}
 1533   		finally {
 1534   			try {
 1535   				stream.close();
 1536   			}
 1537   			catch (IOException ioe) {
 1538   				log.warn( "could not close input stream for: " + resourceName, ioe );
 1539   			}
 1540   		}
 1541   
 1542   		return doConfigure( doc );
 1543   
 1544   	}
 1545   
 1546   	/**
 1547   	 * Use the mappings and properties specified in the given XML document.
 1548   	 * The format of the file is defined in
 1549   	 * <tt>hibernate-configuration-3.0.dtd</tt>.
 1550   	 *
 1551   	 * @param document an XML document from which you wish to load the configuration
 1552   	 * @return A configuration configured via the <tt>Document</tt>
 1553   	 * @throws HibernateException if there is problem in accessing the file.
 1554   	 */
 1555   	public Configuration configure(Document document) throws HibernateException {
 1556   		log.info( "configuring from XML document" );
 1557   		return doConfigure( xmlHelper.createDOMReader().read( document ) );
 1558   	}
 1559   
 1560   	protected Configuration doConfigure(org.dom4j.Document doc) throws HibernateException {
 1561   
 1562   		Element sfNode = doc.getRootElement().element( "session-factory" );
 1563   		String name = sfNode.attributeValue( "name" );
 1564   		if ( name != null ) {
 1565   			properties.setProperty( Environment.SESSION_FACTORY_NAME, name );
 1566   		}
 1567   		addProperties( sfNode );
 1568   		parseSessionFactory( sfNode, name );
 1569   
 1570   		Element secNode = doc.getRootElement().element( "security" );
 1571   		if ( secNode != null ) {
 1572   			parseSecurity( secNode );
 1573   		}
 1574   
 1575   		log.info( "Configured SessionFactory: " + name );
 1576   		log.debug( "properties: " + properties );
 1577   
 1578   		return this;
 1579   
 1580   	}
 1581   
 1582   
 1583   	private void parseSessionFactory(Element sfNode, String name) {
 1584   		Iterator elements = sfNode.elementIterator();
 1585   		while ( elements.hasNext() ) {
 1586   			Element subelement = (Element) elements.next();
 1587   			String subelementName = subelement.getName();
 1588   			if ( "mapping".equals( subelementName ) ) {
 1589   				parseMappingElement( subelement, name );
 1590   			}
 1591   			else if ( "class-cache".equals( subelementName ) ) {
 1592   				String className = subelement.attributeValue( "class" );
 1593   				Attribute regionNode = subelement.attribute( "region" );
 1594   				final String region = ( regionNode == null ) ? className : regionNode.getValue();
 1595   				boolean includeLazy = !"non-lazy".equals( subelement.attributeValue( "include" ) );
 1596   				setCacheConcurrencyStrategy( className, subelement.attributeValue( "usage" ), region, includeLazy );
 1597   			}
 1598   			else if ( "collection-cache".equals( subelementName ) ) {
 1599   				String role = subelement.attributeValue( "collection" );
 1600   				Attribute regionNode = subelement.attribute( "region" );
 1601   				final String region = ( regionNode == null ) ? role : regionNode.getValue();
 1602   				setCollectionCacheConcurrencyStrategy( role, subelement.attributeValue( "usage" ), region );
 1603   			}
 1604   			else if ( "listener".equals( subelementName ) ) {
 1605   				parseListener( subelement );
 1606   			}
 1607   			else if ( "event".equals( subelementName ) ) {
 1608   				parseEvent( subelement );
 1609   			}
 1610   		}
 1611   	}
 1612   
 1613   	protected void parseMappingElement(Element subelement, String name) {
 1614   		Attribute rsrc = subelement.attribute( "resource" );
 1615   		Attribute file = subelement.attribute( "file" );
 1616   		Attribute jar = subelement.attribute( "jar" );
 1617   		Attribute pkg = subelement.attribute( "package" );
 1618   		Attribute clazz = subelement.attribute( "class" );
 1619   		if ( rsrc != null ) {
 1620   			log.debug( name + "<-" + rsrc );
 1621   			addResource( rsrc.getValue() );
 1622   		}
 1623   		else if ( jar != null ) {
 1624   			log.debug( name + "<-" + jar );
 1625   			addJar( new File( jar.getValue() ) );
 1626   		}
 1627   		else if ( pkg != null ) {
 1628   			throw new MappingException(
 1629   					"An AnnotationConfiguration instance is required to use <mapping package=\"" +
 1630   					pkg.getValue() + "\"/>"
 1631   				);
 1632   		}
 1633   		else if ( clazz != null ) {
 1634   			throw new MappingException(
 1635   					"An AnnotationConfiguration instance is required to use <mapping class=\"" +
 1636   					clazz.getValue() + "\"/>"
 1637   				);
 1638   		}
 1639   		else {
 1640   			if ( file == null ) {
 1641   				throw new MappingException(
 1642   						"<mapping> element in configuration specifies no attributes"
 1643   					);
 1644   			}
 1645   			log.debug( name + "<-" + file );
 1646   			addFile( file.getValue() );
 1647   		}
 1648   	}
 1649   
 1650   	private void parseSecurity(Element secNode) {
 1651   		String contextId = secNode.attributeValue( "context" );
 1652         setProperty(Environment.JACC_CONTEXTID, contextId);
 1653   		log.info( "JACC contextID: " + contextId );
 1654   		JACCConfiguration jcfg = new JACCConfiguration( contextId );
 1655   		Iterator grantElements = secNode.elementIterator();
 1656   		while ( grantElements.hasNext() ) {
 1657   			Element grantElement = (Element) grantElements.next();
 1658   			String elementName = grantElement.getName();
 1659   			if ( "grant".equals( elementName ) ) {
 1660   				jcfg.addPermission(
 1661   						grantElement.attributeValue( "role" ),
 1662   						grantElement.attributeValue( "entity-name" ),
 1663   						grantElement.attributeValue( "actions" )
 1664   					);
 1665   			}
 1666   		}
 1667   	}
 1668   
 1669   	private void parseEvent(Element element) {
 1670   		String type = element.attributeValue( "type" );
 1671   		List listeners = element.elements();
 1672   		String[] listenerClasses = new String[ listeners.size() ];
 1673   		for ( int i = 0; i < listeners.size() ; i++ ) {
 1674   			listenerClasses[i] = ( (Element) listeners.get( i ) ).attributeValue( "class" );
 1675   		}
 1676   		log.debug( "Event listeners: " + type + "=" + StringHelper.toString( listenerClasses ) );
 1677   		setListeners( type, listenerClasses );
 1678   	}
 1679   
 1680   	private void parseListener(Element element) {
 1681   		String type = element.attributeValue( "type" );
 1682   		if ( type == null ) {
 1683   			throw new MappingException( "No type specified for listener" );
 1684   		}
 1685   		String impl = element.attributeValue( "class" );
 1686   		log.debug( "Event listener: " + type + "=" + impl );
 1687   		setListeners( type, new String[]{impl} );
 1688   	}
 1689   
 1690   	public void setListener(String type, String listener) {
 1691   		String[] listeners = null;
 1692   		if ( listener != null ) {
 1693   			listeners = (String[]) Array.newInstance( String.class, 1 );
 1694   			listeners[0] = listener;
 1695   		}
 1696   		setListeners( type, listeners );
 1697   	}
 1698   
 1699   	public void setListeners(String type, String[] listenerClasses) {
 1700   		Object[] listeners = null;
 1701   		if ( listenerClasses != null ) {
 1702   			listeners = (Object[]) Array.newInstance( eventListeners.getListenerClassFor(type), listenerClasses.length );
 1703   			for ( int i = 0; i < listeners.length ; i++ ) {
 1704   				try {
 1705   					listeners[i] = ReflectHelper.classForName( listenerClasses[i] ).newInstance();
 1706   				}
 1707   				catch (Exception e) {
 1708   					throw new MappingException(
 1709   							"Unable to instantiate specified event (" + type + ") listener class: " + listenerClasses[i],
 1710   							e
 1711   						);
 1712   				}
 1713   			}
 1714   		}
 1715   		setListeners( type, listeners );
 1716   	}
 1717   
 1718   	public void setListener(String type, Object listener) {
 1719   		Object[] listeners = null;
 1720   		if ( listener != null ) {
 1721   			listeners = (Object[]) Array.newInstance( eventListeners.getListenerClassFor(type), 1 );
 1722   			listeners[0] = listener;
 1723   		}
 1724   		setListeners( type, listeners );
 1725   	}
 1726   
 1727   	public void setListeners(String type, Object[] listeners) {
 1728   		if ( "auto-flush".equals( type ) ) {
 1729   			if ( listeners == null ) {
 1730   				eventListeners.setAutoFlushEventListeners( new AutoFlushEventListener[]{} );
 1731   			}
 1732   			else {
 1733   				eventListeners.setAutoFlushEventListeners( (AutoFlushEventListener[]) listeners );
 1734   			}
 1735   		}
 1736   		else if ( "merge".equals( type ) ) {
 1737   			if ( listeners == null ) {
 1738   				eventListeners.setMergeEventListeners( new MergeEventListener[]{} );
 1739   			}
 1740   			else {
 1741   				eventListeners.setMergeEventListeners( (MergeEventListener[]) listeners );
 1742   			}
 1743   		}
 1744   		else if ( "create".equals( type ) ) {
 1745   			if ( listeners == null ) {
 1746   				eventListeners.setPersistEventListeners( new PersistEventListener[]{} );
 1747   			}
 1748   			else {
 1749   				eventListeners.setPersistEventListeners( (PersistEventListener[]) listeners );
 1750   			}
 1751   		}
 1752   		else if ( "create-onflush".equals( type ) ) {
 1753   			if ( listeners == null ) {
 1754   				eventListeners.setPersistOnFlushEventListeners( new PersistEventListener[]{} );
 1755   			}
 1756   			else {
 1757   				eventListeners.setPersistOnFlushEventListeners( (PersistEventListener[]) listeners );
 1758   			}
 1759   		}
 1760   		else if ( "delete".equals( type ) ) {
 1761   			if ( listeners == null ) {
 1762   				eventListeners.setDeleteEventListeners( new DeleteEventListener[]{} );
 1763   			}
 1764   			else {
 1765   				eventListeners.setDeleteEventListeners( (DeleteEventListener[]) listeners );
 1766   			}
 1767   		}
 1768   		else if ( "dirty-check".equals( type ) ) {
 1769   			if ( listeners == null ) {
 1770   				eventListeners.setDirtyCheckEventListeners( new DirtyCheckEventListener[]{} );
 1771   			}
 1772   			else {
 1773   				eventListeners.setDirtyCheckEventListeners( (DirtyCheckEventListener[]) listeners );
 1774   			}
 1775   		}
 1776   		else if ( "evict".equals( type ) ) {
 1777   			if ( listeners == null ) {
 1778   				eventListeners.setEvictEventListeners( new EvictEventListener[]{} );
 1779   			}
 1780   			else {
 1781   				eventListeners.setEvictEventListeners( (EvictEventListener[]) listeners );
 1782   			}
 1783   		}
 1784   		else if ( "flush".equals( type ) ) {
 1785   			if ( listeners == null ) {
 1786   				eventListeners.setFlushEventListeners( new FlushEventListener[]{} );
 1787   			}
 1788   			else {
 1789   				eventListeners.setFlushEventListeners( (FlushEventListener[]) listeners );
 1790   			}
 1791   		}
 1792   		else if ( "flush-entity".equals( type ) ) {
 1793   			if ( listeners == null ) {
 1794   				eventListeners.setFlushEntityEventListeners( new FlushEntityEventListener[]{} );
 1795   			}
 1796   			else {
 1797   				eventListeners.setFlushEntityEventListeners( (FlushEntityEventListener[]) listeners );
 1798   			}
 1799   		}
 1800   		else if ( "load".equals( type ) ) {
 1801   			if ( listeners == null ) {
 1802   				eventListeners.setLoadEventListeners( new LoadEventListener[]{} );
 1803   			}
 1804   			else {
 1805   				eventListeners.setLoadEventListeners( (LoadEventListener[]) listeners );
 1806   			}
 1807   		}
 1808   		else if ( "load-collection".equals( type ) ) {
 1809   			if ( listeners == null ) {
 1810   				eventListeners.setInitializeCollectionEventListeners(
 1811   						new InitializeCollectionEventListener[]{}
 1812   					);
 1813   			}
 1814   			else {
 1815   				eventListeners.setInitializeCollectionEventListeners(
 1816   						(InitializeCollectionEventListener[]) listeners
 1817   					);
 1818   			}
 1819   		}
 1820   		else if ( "lock".equals( type ) ) {
 1821   			if ( listeners == null ) {
 1822   				eventListeners.setLockEventListeners( new LockEventListener[]{} );
 1823   			}
 1824   			else {
 1825   				eventListeners.setLockEventListeners( (LockEventListener[]) listeners );
 1826   			}
 1827   		}
 1828   		else if ( "refresh".equals( type ) ) {
 1829   			if ( listeners == null ) {
 1830   				eventListeners.setRefreshEventListeners( new RefreshEventListener[]{} );
 1831   			}
 1832   			else {
 1833   				eventListeners.setRefreshEventListeners( (RefreshEventListener[]) listeners );
 1834   			}
 1835   		}
 1836   		else if ( "replicate".equals( type ) ) {
 1837   			if ( listeners == null ) {
 1838   				eventListeners.setReplicateEventListeners( new ReplicateEventListener[]{} );
 1839   			}
 1840   			else {
 1841   				eventListeners.setReplicateEventListeners( (ReplicateEventListener[]) listeners );
 1842   			}
 1843   		}
 1844   		else if ( "save-update".equals( type ) ) {
 1845   			if ( listeners == null ) {
 1846   				eventListeners.setSaveOrUpdateEventListeners( new SaveOrUpdateEventListener[]{} );
 1847   			}
 1848   			else {
 1849   				eventListeners.setSaveOrUpdateEventListeners( (SaveOrUpdateEventListener[]) listeners );
 1850   			}
 1851   		}
 1852   		else if ( "save".equals( type ) ) {
 1853   			if ( listeners == null ) {
 1854   				eventListeners.setSaveEventListeners( new SaveOrUpdateEventListener[]{} );
 1855   			}
 1856   			else {
 1857   				eventListeners.setSaveEventListeners( (SaveOrUpdateEventListener[]) listeners );
 1858   			}
 1859   		}
 1860   		else if ( "update".equals( type ) ) {
 1861   			if ( listeners == null ) {
 1862   				eventListeners.setUpdateEventListeners( new SaveOrUpdateEventListener[]{} );
 1863   			}
 1864   			else {
 1865   				eventListeners.setUpdateEventListeners( (SaveOrUpdateEventListener[]) listeners );
 1866   			}
 1867   		}
 1868   		else if ( "pre-load".equals( type ) ) {
 1869   			if ( listeners == null ) {
 1870   				eventListeners.setPreLoadEventListeners( new PreLoadEventListener[]{} );
 1871   			}
 1872   			else {
 1873   				eventListeners.setPreLoadEventListeners( (PreLoadEventListener[]) listeners );
 1874   			}
 1875   		}
 1876   		else if ( "pre-update".equals( type ) ) {
 1877   			if ( listeners == null ) {
 1878   				eventListeners.setPreUpdateEventListeners( new PreUpdateEventListener[]{} );
 1879   			}
 1880   			else {
 1881   				eventListeners.setPreUpdateEventListeners( (PreUpdateEventListener[]) listeners );
 1882   			}
 1883   		}
 1884   		else if ( "pre-delete".equals( type ) ) {
 1885   			if ( listeners == null ) {
 1886   				eventListeners.setPreDeleteEventListeners( new PreDeleteEventListener[]{} );
 1887   			}
 1888   			else {
 1889   				eventListeners.setPreDeleteEventListeners( (PreDeleteEventListener[]) listeners );
 1890   			}
 1891   		}
 1892   		else if ( "pre-insert".equals( type ) ) {
 1893   			if ( listeners == null ) {
 1894   				eventListeners.setPreInsertEventListeners( new PreInsertEventListener[]{} );
 1895   			}
 1896   			else {
 1897   				eventListeners.setPreInsertEventListeners( (PreInsertEventListener[]) listeners );
 1898   			}
 1899   		}
 1900   		else if ( "pre-collection-recreate".equals( type ) ) {
 1901   			if ( listeners == null ) {
 1902   				eventListeners.setPreCollectionRecreateEventListeners( new PreCollectionRecreateEventListener[]{} );
 1903   			}
 1904   			else {
 1905   				eventListeners.setPreCollectionRecreateEventListeners( (PreCollectionRecreateEventListener[]) listeners );
 1906   			}
 1907   		}
 1908   		else if ( "pre-collection-remove".equals( type ) ) {
 1909   			if ( listeners == null ) {
 1910   				eventListeners.setPreCollectionRemoveEventListeners( new PreCollectionRemoveEventListener[]{} );
 1911   			}
 1912   			else {
 1913   				eventListeners.setPreCollectionRemoveEventListeners( ( PreCollectionRemoveEventListener[]) listeners );
 1914   			}
 1915   		}
 1916   		else if ( "pre-collection-update".equals( type ) ) {
 1917   			if ( listeners == null ) {
 1918   				eventListeners.setPreCollectionUpdateEventListeners( new PreCollectionUpdateEventListener[]{} );
 1919   			}
 1920   			else {
 1921   				eventListeners.setPreCollectionUpdateEventListeners( ( PreCollectionUpdateEventListener[]) listeners );
 1922   			}
 1923   		}
 1924   		else if ( "post-load".equals( type ) ) {
 1925   			if ( listeners == null ) {
 1926   				eventListeners.setPostLoadEventListeners( new PostLoadEventListener[]{} );
 1927   			}
 1928   			else {
 1929   				eventListeners.setPostLoadEventListeners( (PostLoadEventListener[]) listeners );
 1930   			}
 1931   		}
 1932   		else if ( "post-update".equals( type ) ) {
 1933   			if ( listeners == null ) {
 1934   				eventListeners.setPostUpdateEventListeners( new PostUpdateEventListener[]{} );
 1935   			}
 1936   			else {
 1937   				eventListeners.setPostUpdateEventListeners( (PostUpdateEventListener[]) listeners );
 1938   			}
 1939   		}
 1940   		else if ( "post-delete".equals( type ) ) {
 1941   			if ( listeners == null ) {
 1942   				eventListeners.setPostDeleteEventListeners( new PostDeleteEventListener[]{} );
 1943   			}
 1944   			else {
 1945   				eventListeners.setPostDeleteEventListeners( (PostDeleteEventListener[]) listeners );
 1946   			}
 1947   		}
 1948   		else if ( "post-insert".equals( type ) ) {
 1949   			if ( listeners == null ) {
 1950   				eventListeners.setPostInsertEventListeners( new PostInsertEventListener[]{} );
 1951   			}
 1952   			else {
 1953   				eventListeners.setPostInsertEventListeners( (PostInsertEventListener[]) listeners );
 1954   			}
 1955   		}
 1956   		else if ( "post-commit-update".equals( type ) ) {
 1957   			if ( listeners == null ) {
 1958   				eventListeners.setPostCommitUpdateEventListeners(
 1959   						new PostUpdateEventListener[]{}
 1960   					);
 1961   			}
 1962   			else {
 1963   				eventListeners.setPostCommitUpdateEventListeners( (PostUpdateEventListener[]) listeners );
 1964   			}
 1965   		}
 1966   		else if ( "post-commit-delete".equals( type ) ) {
 1967   			if ( listeners == null ) {
 1968   				eventListeners.setPostCommitDeleteEventListeners(
 1969   						new PostDeleteEventListener[]{}
 1970   					);
 1971   			}
 1972   			else {
 1973   				eventListeners.setPostCommitDeleteEventListeners( (PostDeleteEventListener[]) listeners );
 1974   			}
 1975   		}
 1976   		else if ( "post-commit-insert".equals( type ) ) {
 1977   			if ( listeners == null ) {
 1978   				eventListeners.setPostCommitInsertEventListeners(
 1979   						new PostInsertEventListener[]{}
 1980   				);
 1981   			}
 1982   			else {
 1983   				eventListeners.setPostCommitInsertEventListeners( (PostInsertEventListener[]) listeners );
 1984   			}
 1985   		}
 1986   		else if ( "post-collection-recreate".equals( type ) ) {
 1987   			if ( listeners == null ) {
 1988   				eventListeners.setPostCollectionRecreateEventListeners( new PostCollectionRecreateEventListener[]{} );
 1989   			}
 1990   			else {
 1991   				eventListeners.setPostCollectionRecreateEventListeners( (PostCollectionRecreateEventListener[]) listeners );
 1992   			}
 1993   		}
 1994   		else if ( "post-collection-remove".equals( type ) ) {
 1995   			if ( listeners == null ) {
 1996   				eventListeners.setPostCollectionRemoveEventListeners( new PostCollectionRemoveEventListener[]{} );
 1997   			}
 1998   			else {
 1999   				eventListeners.setPostCollectionRemoveEventListeners( ( PostCollectionRemoveEventListener[]) listeners );
 2000   			}
 2001   		}
 2002   		else if ( "post-collection-update".equals( type ) ) {
 2003   			if ( listeners == null ) {
 2004   				eventListeners.setPostCollectionUpdateEventListeners( new PostCollectionUpdateEventListener[]{} );
 2005   			}
 2006   			else {
 2007   				eventListeners.setPostCollectionUpdateEventListeners( ( PostCollectionUpdateEventListener[]) listeners );
 2008   			}
 2009   		}
 2010   		else {
 2011   			throw new MappingException("Unrecognized listener type [" + type + "]");
 2012   		}
 2013   	}
 2014   
 2015   	public EventListeners getEventListeners() {
 2016   		return eventListeners;
 2017   	}
 2018   
 2019   	RootClass getRootClassMapping(String clazz) throws MappingException {
 2020   		try {
 2021   			return (RootClass) getClassMapping( clazz );
 2022   		}
 2023   		catch (ClassCastException cce) {
 2024   			throw new MappingException( "You may only specify a cache for root <class> mappings" );
 2025   		}
 2026   	}
 2027   
 2028   	/**
 2029   	 * Set up a cache for an entity class
 2030   	 *
 2031   	 * @param clazz
 2032   	 * @param concurrencyStrategy
 2033   	 * @return Configuration
 2034   	 * @throws MappingException
 2035   	 */
 2036   	public Configuration setCacheConcurrencyStrategy(String clazz, String concurrencyStrategy)
 2037   			throws MappingException {
 2038   		setCacheConcurrencyStrategy( clazz, concurrencyStrategy, clazz );
 2039   		return this;
 2040   	}
 2041   
 2042   	public void setCacheConcurrencyStrategy(String clazz, String concurrencyStrategy, String region)
 2043   			throws MappingException {
 2044   		setCacheConcurrencyStrategy( clazz, concurrencyStrategy, region, true );
 2045   	}
 2046   
 2047   	void setCacheConcurrencyStrategy(String clazz, String concurrencyStrategy, String region, boolean includeLazy)
 2048   			throws MappingException {
 2049   		RootClass rootClass = getRootClassMapping( clazz );
 2050   		if ( rootClass == null ) {
 2051   			throw new MappingException( "Cannot cache an unknown entity: " + clazz );
 2052   		}
 2053   		rootClass.setCacheConcurrencyStrategy( concurrencyStrategy );
 2054   		rootClass.setCacheRegionName( region );
 2055   		rootClass.setLazyPropertiesCacheable( includeLazy );
 2056   	}
 2057   
 2058   	/**
 2059   	 * Set up a cache for a collection role
 2060   	 *
 2061   	 * @param collectionRole
 2062   	 * @param concurrencyStrategy
 2063   	 * @return Configuration
 2064   	 * @throws MappingException
 2065   	 */
 2066   	public Configuration setCollectionCacheConcurrencyStrategy(String collectionRole, String concurrencyStrategy)
 2067   			throws MappingException {
 2068   		setCollectionCacheConcurrencyStrategy( collectionRole, concurrencyStrategy, collectionRole );
 2069   		return this;
 2070   	}
 2071   
 2072   	public void setCollectionCacheConcurrencyStrategy(String collectionRole, String concurrencyStrategy, String region)
 2073   			throws MappingException {
 2074   		Collection collection = getCollectionMapping( collectionRole );
 2075   		if ( collection == null ) {
 2076   			throw new MappingException( "Cannot cache an unknown collection: " + collectionRole );
 2077   		}
 2078   		collection.setCacheConcurrencyStrategy( concurrencyStrategy );
 2079   		collection.setCacheRegionName( region );
 2080   	}
 2081   
 2082   	/**
 2083   	 * Get the query language imports
 2084   	 *
 2085   	 * @return a mapping from "import" names to fully qualified class names
 2086   	 */
 2087   	public Map getImports() {
 2088   		return imports;
 2089   	}
 2090   
 2091   	/**
 2092   	 * Create an object-oriented view of the configuration properties
 2093   	 */
 2094   	public Settings buildSettings() throws HibernateException {
 2095   		Properties clone = ( Properties ) properties.clone();
 2096   		PropertiesHelper.resolvePlaceHolders( clone );
 2097   		return settingsFactory.buildSettings( clone );
 2098   	}
 2099   
 2100   	public Settings buildSettings(Properties props) throws HibernateException {
 2101   		return settingsFactory.buildSettings( props );
 2102   	}
 2103   
 2104   	public Map getNamedSQLQueries() {
 2105   		return namedSqlQueries;
 2106   	}
 2107   
 2108   	public Map getSqlResultSetMappings() {
 2109   		return sqlResultSetMappings;
 2110   	}
 2111   
 2112   	/**
 2113   	 * @return the NamingStrategy.
 2114   	 */
 2115   	public NamingStrategy getNamingStrategy() {
 2116   		return namingStrategy;
 2117   	}
 2118   
 2119   	/**
 2120   	 * Set a custom naming strategy
 2121   	 *
 2122   	 * @param namingStrategy the NamingStrategy to set
 2123   	 */
 2124   	public Configuration setNamingStrategy(NamingStrategy namingStrategy) {
 2125   		this.namingStrategy = namingStrategy;
 2126   		return this;
 2127   	}
 2128   
 2129   	public Mapping buildMapping() {
 2130   		return new Mapping() {
 2131   			/**
 2132   			 * Returns the identifier type of a mapped class
 2133   			 */
 2134   			public Type getIdentifierType(String persistentClass) throws MappingException {
 2135   				PersistentClass pc = ( (PersistentClass) classes.get( persistentClass ) );
 2136   				if ( pc == null ) {
 2137   					throw new MappingException( "persistent class not known: " + persistentClass );
 2138   				}
 2139   				return pc.getIdentifier().getType();
 2140   			}
 2141   
 2142   			public String getIdentifierPropertyName(String persistentClass) throws MappingException {
 2143   				final PersistentClass pc = (PersistentClass) classes.get( persistentClass );
 2144   				if ( pc == null ) {
 2145   					throw new MappingException( "persistent class not known: " + persistentClass );
 2146   				}
 2147   				if ( !pc.hasIdentifierProperty() ) {
 2148   					return null;
 2149   				}
 2150   				return pc.getIdentifierProperty().getName();
 2151   			}
 2152   
 2153   			public Type getReferencedPropertyType(String persistentClass, String propertyName) throws MappingException {
 2154   				final PersistentClass pc = (PersistentClass) classes.get( persistentClass );
 2155   				if ( pc == null ) {
 2156   					throw new MappingException( "persistent class not known: " + persistentClass );
 2157   				}
 2158   				Property prop = pc.getReferencedProperty( propertyName );
 2159   				if ( prop == null ) {
 2160   					throw new MappingException(
 2161   							"property not known: " +
 2162   							persistentClass + '.' + propertyName
 2163   						);
 2164   				}
 2165   				return prop.getType();
 2166   			}
 2167   		};
 2168   	}
 2169   
 2170   	private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
 2171   		ois.defaultReadObject();
 2172   		this.mapping = buildMapping();
 2173   		xmlHelper = new XMLHelper();
 2174   	}
 2175   
 2176   	public Map getFilterDefinitions() {
 2177   		return filterDefinitions;
 2178   	}
 2179   
 2180   	public void addFilterDefinition(FilterDefinition definition) {
 2181   		filterDefinitions.put( definition.getFilterName(), definition );
 2182   	}
 2183   
 2184   	public void addAuxiliaryDatabaseObject(AuxiliaryDatabaseObject object) {
 2185   		auxiliaryDatabaseObjects.add( object );
 2186   	}
 2187   
 2188   	public Map getSqlFunctions() {
 2189   		return sqlFunctions;
 2190   	}
 2191   
 2192   	public void addSqlFunction(String functionName, SQLFunction function) {
 2193   		sqlFunctions.put( functionName, function );
 2194   	}
 2195   
 2196   	public SessionFactoryObserver getSessionFactoryObserver() {
 2197   		return sessionFactoryObserver;
 2198   	}
 2199   
 2200   	public void setSessionFactoryObserver(SessionFactoryObserver sessionFactoryObserver) {
 2201   		this.sessionFactoryObserver = sessionFactoryObserver;
 2202   	}
 2203   }

Save This Page
Home » hibernate-distribution-3.3.1.GA-dist » org.hibernate » cfg » [javadoc | source]