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

Save This Page
Home » Hibernate-3.3.2.GA » org.hibernate » cfg » [javadoc | source]