0001: //$Id: Configuration.java 10842 2006-11-17 18:38:15Z max.andersen@jboss.com $
0002: package org.hibernate.cfg;
0003:
0004: import java.io.File;
0005: import java.io.FileInputStream;
0006: import java.io.FileNotFoundException;
0007: import java.io.FileOutputStream;
0008: import java.io.IOException;
0009: import java.io.InputStream;
0010: import java.io.ObjectInputStream;
0011: import java.io.Serializable;
0012: import java.io.StringReader;
0013: import java.lang.reflect.Array;
0014: import java.net.URL;
0015: import java.util.ArrayList;
0016: import java.util.Enumeration;
0017: import java.util.HashMap;
0018: import java.util.HashSet;
0019: import java.util.Iterator;
0020: import java.util.List;
0021: import java.util.ListIterator;
0022: import java.util.Map;
0023: import java.util.Properties;
0024: import java.util.Set;
0025: import java.util.TreeMap;
0026: import java.util.jar.JarFile;
0027: import java.util.zip.ZipEntry;
0028:
0029: import org.apache.commons.logging.Log;
0030: import org.apache.commons.logging.LogFactory;
0031: import org.dom4j.Attribute;
0032: import org.dom4j.DocumentException;
0033: import org.dom4j.Element;
0034: import org.hibernate.EmptyInterceptor;
0035: import org.hibernate.HibernateException;
0036: import org.hibernate.Interceptor;
0037: import org.hibernate.InvalidMappingException;
0038: import org.hibernate.MappingException;
0039: import org.hibernate.MappingNotFoundException;
0040: import org.hibernate.SessionFactory;
0041: import org.hibernate.proxy.EntityNotFoundDelegate;
0042: import org.hibernate.dialect.Dialect;
0043: import org.hibernate.dialect.MySQLDialect;
0044: import org.hibernate.dialect.function.SQLFunction;
0045: import org.hibernate.engine.FilterDefinition;
0046: import org.hibernate.engine.Mapping;
0047: import org.hibernate.event.AutoFlushEventListener;
0048: import org.hibernate.event.DeleteEventListener;
0049: import org.hibernate.event.DirtyCheckEventListener;
0050: import org.hibernate.event.EventListeners;
0051: import org.hibernate.event.EvictEventListener;
0052: import org.hibernate.event.FlushEntityEventListener;
0053: import org.hibernate.event.FlushEventListener;
0054: import org.hibernate.event.InitializeCollectionEventListener;
0055: import org.hibernate.event.LoadEventListener;
0056: import org.hibernate.event.LockEventListener;
0057: import org.hibernate.event.MergeEventListener;
0058: import org.hibernate.event.PersistEventListener;
0059: import org.hibernate.event.PostDeleteEventListener;
0060: import org.hibernate.event.PostInsertEventListener;
0061: import org.hibernate.event.PostLoadEventListener;
0062: import org.hibernate.event.PostUpdateEventListener;
0063: import org.hibernate.event.PreDeleteEventListener;
0064: import org.hibernate.event.PreInsertEventListener;
0065: import org.hibernate.event.PreLoadEventListener;
0066: import org.hibernate.event.PreUpdateEventListener;
0067: import org.hibernate.event.RefreshEventListener;
0068: import org.hibernate.event.ReplicateEventListener;
0069: import org.hibernate.event.SaveOrUpdateEventListener;
0070: import org.hibernate.id.IdentifierGenerator;
0071: import org.hibernate.id.PersistentIdentifierGenerator;
0072: import org.hibernate.impl.SessionFactoryImpl;
0073: import org.hibernate.mapping.AuxiliaryDatabaseObject;
0074: import org.hibernate.mapping.Collection;
0075: import org.hibernate.mapping.ForeignKey;
0076: import org.hibernate.mapping.IdentifierCollection;
0077: import org.hibernate.mapping.Index;
0078: import org.hibernate.mapping.PersistentClass;
0079: import org.hibernate.mapping.Property;
0080: import org.hibernate.mapping.RootClass;
0081: import org.hibernate.mapping.SimpleValue;
0082: import org.hibernate.mapping.Table;
0083: import org.hibernate.mapping.UniqueKey;
0084: import org.hibernate.secure.JACCConfiguration;
0085: import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
0086: import org.hibernate.tool.hbm2ddl.TableMetadata;
0087: import org.hibernate.type.SerializationException;
0088: import org.hibernate.type.Type;
0089: import org.hibernate.util.ArrayHelper;
0090: import org.hibernate.util.CollectionHelper;
0091: import org.hibernate.util.ConfigHelper;
0092: import org.hibernate.util.ReflectHelper;
0093: import org.hibernate.util.SerializationHelper;
0094: import org.hibernate.util.StringHelper;
0095: import org.hibernate.util.XMLHelper;
0096: import org.hibernate.util.PropertiesHelper;
0097: import org.w3c.dom.Document;
0098: import org.xml.sax.EntityResolver;
0099: import org.xml.sax.InputSource;
0100:
0101: /**
0102: * An instance of <tt>Configuration</tt> allows the application
0103: * to specify properties and mapping documents to be used when
0104: * creating a <tt>SessionFactory</tt>. Usually an application will create
0105: * a single <tt>Configuration</tt>, build a single instance of
0106: * <tt>SessionFactory</tt> and then instantiate <tt>Session</tt>s in
0107: * threads servicing client requests. The <tt>Configuration</tt> is meant
0108: * only as an initialization-time object. <tt>SessionFactory</tt>s are
0109: * immutable and do not retain any association back to the
0110: * <tt>Configuration</tt>.<br>
0111: * <br>
0112: * A new <tt>Configuration</tt> will use the properties specified in
0113: * <tt>hibernate.properties</tt> by default.
0114: *
0115: * @author Gavin King
0116: * @see org.hibernate.SessionFactory
0117: */
0118: public class Configuration implements Serializable {
0119:
0120: private static Log log = LogFactory.getLog(Configuration.class);
0121:
0122: protected Map classes;
0123: protected Map imports;
0124: protected Map collections;
0125: protected Map tables;
0126: protected List auxiliaryDatabaseObjects;
0127: protected Map sqlFunctions;
0128: protected Map namedQueries;
0129: protected Map namedSqlQueries;
0130: /**
0131: * Map<String, SqlResultSetMapping> result set name, result set description
0132: */
0133: protected Map sqlResultSetMappings;
0134: protected Map filterDefinitions;
0135: protected List secondPasses;
0136: protected List propertyReferences;
0137: // protected List extendsQueue;
0138: protected Map extendsQueue;
0139: protected Map tableNameBinding;
0140: protected Map columnNameBindingPerTable;
0141: private Interceptor interceptor;
0142: private Properties properties;
0143: private EntityResolver entityResolver;
0144: private EntityNotFoundDelegate entityNotFoundDelegate;
0145:
0146: protected transient XMLHelper xmlHelper;
0147: protected transient Map typeDefs;
0148:
0149: protected NamingStrategy namingStrategy;
0150:
0151: private EventListeners eventListeners;
0152:
0153: protected final SettingsFactory settingsFactory;
0154:
0155: protected void reset() {
0156: classes = new HashMap();
0157: imports = new HashMap();
0158: collections = new HashMap();
0159: tables = new TreeMap();
0160: namedQueries = new HashMap();
0161: namedSqlQueries = new HashMap();
0162: sqlResultSetMappings = new HashMap();
0163: xmlHelper = new XMLHelper();
0164: typeDefs = new HashMap();
0165: propertyReferences = new ArrayList();
0166: secondPasses = new ArrayList();
0167: interceptor = EmptyInterceptor.INSTANCE;
0168: properties = Environment.getProperties();
0169: entityResolver = XMLHelper.DEFAULT_DTD_RESOLVER;
0170: eventListeners = new EventListeners();
0171: filterDefinitions = new HashMap();
0172: // extendsQueue = new ArrayList();
0173: extendsQueue = new HashMap();
0174: auxiliaryDatabaseObjects = new ArrayList();
0175: tableNameBinding = new HashMap();
0176: columnNameBindingPerTable = new HashMap();
0177: namingStrategy = DefaultNamingStrategy.INSTANCE;
0178: sqlFunctions = new HashMap();
0179: }
0180:
0181: private transient Mapping mapping = buildMapping();
0182:
0183: protected Configuration(SettingsFactory settingsFactory) {
0184: this .settingsFactory = settingsFactory;
0185: reset();
0186: }
0187:
0188: public Configuration() {
0189: this (new SettingsFactory());
0190: }
0191:
0192: /**
0193: * Iterate the entity mappings
0194: *
0195: * @return Iterator of the entity mappings currently contained in the configuration.
0196: */
0197: public Iterator getClassMappings() {
0198: return classes.values().iterator();
0199: }
0200:
0201: /**
0202: * Iterate the collection mappings
0203: *
0204: * @return Iterator of the collection mappings currently contained in the configuration.
0205: */
0206: public Iterator getCollectionMappings() {
0207: return collections.values().iterator();
0208: }
0209:
0210: /**
0211: * Iterate the table mappings
0212: *
0213: * @return Iterator of the table mappings currently contained in the configuration.
0214: */
0215: public Iterator getTableMappings() {
0216: return tables.values().iterator();
0217: }
0218:
0219: /**
0220: * Get the mapping for a particular entity
0221: *
0222: * @param entityName An entity name.
0223: * @return the entity mapping information
0224: */
0225: public PersistentClass getClassMapping(String entityName) {
0226: return (PersistentClass) classes.get(entityName);
0227: }
0228:
0229: /**
0230: * Get the mapping for a particular collection role
0231: *
0232: * @param role a collection role
0233: * @return The collection mapping information
0234: */
0235: public Collection getCollectionMapping(String role) {
0236: return (Collection) collections.get(role);
0237: }
0238:
0239: /**
0240: * Set a custom entity resolver. This entity resolver must be
0241: * set before addXXX(misc) call.
0242: * Default value is {@link org.hibernate.util.DTDEntityResolver}
0243: *
0244: * @param entityResolver entity resolver to use
0245: */
0246: public void setEntityResolver(EntityResolver entityResolver) {
0247: this .entityResolver = entityResolver;
0248: }
0249:
0250: public EntityResolver getEntityResolver() {
0251: return entityResolver;
0252: }
0253:
0254: /**
0255: * Retrieve the user-supplied delegate to handle non-existent entity
0256: * scenarios. May be null.
0257: *
0258: * @return The user-supplied delegate
0259: */
0260: public EntityNotFoundDelegate getEntityNotFoundDelegate() {
0261: return entityNotFoundDelegate;
0262: }
0263:
0264: /**
0265: * Specify a user-supplied delegate to be used to handle scenarios where an entity could not be
0266: * located by specified id. This is mainly intended for EJB3 implementations to be able to
0267: * control how proxy initialization errors should be handled...
0268: *
0269: * @param entityNotFoundDelegate The delegate to use
0270: */
0271: public void setEntityNotFoundDelegate(
0272: EntityNotFoundDelegate entityNotFoundDelegate) {
0273: this .entityNotFoundDelegate = entityNotFoundDelegate;
0274: }
0275:
0276: /**
0277: * Read mappings from a particular XML file
0278: *
0279: * @param xmlFile a path to a file
0280: * @return this (for method chaining purposes)
0281: * @throws org.hibernate.MappingException Indicates inability to locate or parse
0282: * the specified mapping file.
0283: * @see #addFile(java.io.File)
0284: */
0285: public Configuration addFile(String xmlFile)
0286: throws MappingException {
0287: return addFile(new File(xmlFile));
0288: }
0289:
0290: /**
0291: * Read mappings from a particular XML file
0292: *
0293: * @param xmlFile a path to a file
0294: * @return this (for method chaining purposes)
0295: * @throws org.hibernate.MappingException Indicates inability to locate or parse
0296: * the specified mapping file.
0297: */
0298: public Configuration addFile(File xmlFile) throws MappingException {
0299: log.info("Reading mappings from file: " + xmlFile.getPath());
0300: if (!xmlFile.exists()) {
0301: throw new MappingNotFoundException("file", xmlFile
0302: .toString());
0303: }
0304: try {
0305: List errors = new ArrayList();
0306: org.dom4j.Document doc = xmlHelper.createSAXReader(
0307: xmlFile.toString(), errors, entityResolver).read(
0308: xmlFile);
0309: if (errors.size() != 0) {
0310: throw new InvalidMappingException("file", xmlFile
0311: .toString(), (Throwable) errors.get(0));
0312: }
0313: add(doc);
0314: return this ;
0315: } catch (InvalidMappingException e) {
0316: throw e;
0317: } catch (MappingNotFoundException e) {
0318: throw e;
0319: } catch (Exception e) {
0320: throw new InvalidMappingException("file", xmlFile
0321: .toString(), e);
0322: }
0323: }
0324:
0325: /**
0326: * Add a cached mapping file. A cached file is a serialized representation
0327: * of the DOM structure of a particular mapping. It is saved from a previous
0328: * call as a file with the name <tt>xmlFile + ".bin"</tt> where xmlFile is
0329: * the name of the original mapping file.
0330: * </p>
0331: * If a cached <tt>xmlFile + ".bin"</tt> exists and is newer than
0332: * <tt>xmlFile</tt> the <tt>".bin"</tt> file will be read directly. Otherwise
0333: * xmlFile is read and then serialized to <tt>xmlFile + ".bin"</tt> for use
0334: * the next time.
0335: *
0336: * @param xmlFile The cacheable mapping file to be added.
0337: * @return this (for method chaining purposes)
0338: * @throws MappingException Indicates problems reading the cached file or processing
0339: * the non-cached file.
0340: */
0341: public Configuration addCacheableFile(File xmlFile)
0342: throws MappingException {
0343: try {
0344: File cachedFile = new File(xmlFile.getAbsolutePath()
0345: + ".bin");
0346: org.dom4j.Document doc = null;
0347:
0348: final boolean useCachedFile = xmlFile.exists()
0349: && cachedFile.exists()
0350: && xmlFile.lastModified() < cachedFile
0351: .lastModified();
0352:
0353: if (useCachedFile) {
0354: try {
0355: log.info("Reading mappings from cache file: "
0356: + cachedFile);
0357: doc = (org.dom4j.Document) SerializationHelper
0358: .deserialize(new FileInputStream(cachedFile));
0359: } catch (SerializationException e) {
0360: log.warn("Could not deserialize cache file: "
0361: + cachedFile.getPath(), e);
0362: } catch (FileNotFoundException e) {
0363: log.warn(
0364: "I/O reported cached file could not be found : "
0365: + cachedFile.getPath(), e);
0366: }
0367: }
0368:
0369: // if doc is null, then for whatever reason, the cached file cannot be used...
0370: if (doc == null) {
0371: if (!xmlFile.exists()) {
0372: throw new MappingNotFoundException("file", xmlFile
0373: .toString());
0374: }
0375:
0376: log.info("Reading mappings from file: " + xmlFile);
0377: List errors = new ArrayList();
0378: try {
0379: doc = xmlHelper.createSAXReader(
0380: xmlFile.getAbsolutePath(), errors,
0381: entityResolver).read(xmlFile);
0382: if (errors.size() != 0) {
0383: throw new MappingException("invalid mapping",
0384: (Throwable) errors.get(0));
0385: }
0386: } catch (DocumentException e) {
0387: throw new MappingException("invalid mapping", e);
0388: }
0389:
0390: try {
0391: log.debug("Writing cache file for: " + xmlFile
0392: + " to: " + cachedFile);
0393: SerializationHelper.serialize((Serializable) doc,
0394: new FileOutputStream(cachedFile));
0395: } catch (SerializationException e) {
0396: log.warn("Could not write cached file: "
0397: + cachedFile, e);
0398: } catch (FileNotFoundException e) {
0399: log.warn(
0400: "I/O reported error writing cached file : "
0401: + cachedFile.getPath(), e);
0402: }
0403: }
0404:
0405: add(doc);
0406: return this ;
0407:
0408: } catch (InvalidMappingException e) {
0409: throw e;
0410: } catch (MappingNotFoundException e) {
0411: throw e;
0412: } catch (Exception e) {
0413: throw new InvalidMappingException("file", xmlFile
0414: .toString(), e);
0415: }
0416: }
0417:
0418: /**
0419: * Add a cacheable mapping file.
0420: *
0421: * @param xmlFile The name of the file to be added. This must be in a form
0422: * useable to simply construct a {@link java.io.File} instance.
0423: * @return this (for method chaining purposes)
0424: * @throws MappingException Indicates problems reading the cached file or processing
0425: * the non-cached file.
0426: * @see #addCacheableFile(java.io.File)
0427: */
0428: public Configuration addCacheableFile(String xmlFile)
0429: throws MappingException {
0430: return addCacheableFile(new File(xmlFile));
0431: }
0432:
0433: /**
0434: * Read mappings from a <tt>String</tt>
0435: *
0436: * @param xml an XML string
0437: * @return this (for method chaining purposes)
0438: * @throws org.hibernate.MappingException Indicates problems parsing the
0439: * given XML string
0440: */
0441: public Configuration addXML(String xml) throws MappingException {
0442: if (log.isDebugEnabled()) {
0443: log.debug("Mapping XML:\n" + xml);
0444: }
0445: try {
0446: List errors = new ArrayList();
0447: org.dom4j.Document doc = xmlHelper.createSAXReader(
0448: "XML String", errors, entityResolver).read(
0449: new StringReader(xml));
0450: if (errors.size() != 0) {
0451: throw new MappingException("invalid mapping",
0452: (Throwable) errors.get(0));
0453: }
0454: add(doc);
0455: } catch (DocumentException e) {
0456: throw new MappingException(
0457: "Could not parse mapping document in XML string", e);
0458: }
0459: return this ;
0460: }
0461:
0462: /**
0463: * Read mappings from a <tt>URL</tt>
0464: *
0465: * @param url The url for the mapping document to be read.
0466: * @return this (for method chaining purposes)
0467: * @throws MappingException Indicates problems reading the URL or processing
0468: * the mapping document.
0469: */
0470: public Configuration addURL(URL url) throws MappingException {
0471: if (log.isDebugEnabled()) {
0472: log.debug("Reading mapping document from URL:"
0473: + url.toExternalForm());
0474: }
0475: try {
0476: addInputStream(url.openStream());
0477: } catch (InvalidMappingException e) {
0478: throw new InvalidMappingException("URL", url
0479: .toExternalForm(), e.getCause());
0480: } catch (Exception e) {
0481: throw new InvalidMappingException("URL", url
0482: .toExternalForm(), e);
0483: }
0484: return this ;
0485: }
0486:
0487: /**
0488: * Read mappings from a DOM <tt>Document</tt>
0489: *
0490: * @param doc The DOM document
0491: * @return this (for method chaining purposes)
0492: * @throws MappingException Indicates problems reading the DOM or processing
0493: * the mapping document.
0494: */
0495: public Configuration addDocument(Document doc)
0496: throws MappingException {
0497: if (log.isDebugEnabled()) {
0498: log.debug("Mapping document:\n" + doc);
0499: }
0500: add(xmlHelper.createDOMReader().read(doc));
0501: return this ;
0502: }
0503:
0504: /**
0505: * Read mappings from an {@link java.io.InputStream}.
0506: *
0507: * @param xmlInputStream The input stream containing a DOM.
0508: * @return this (for method chaining purposes)
0509: * @throws MappingException Indicates problems reading the stream, or
0510: * processing the contained mapping document.
0511: */
0512: public Configuration addInputStream(InputStream xmlInputStream)
0513: throws MappingException {
0514: try {
0515: List errors = new ArrayList();
0516: org.dom4j.Document doc = xmlHelper.createSAXReader(
0517: "XML InputStream", errors, entityResolver).read(
0518: new InputSource(xmlInputStream));
0519: if (errors.size() != 0) {
0520: throw new InvalidMappingException("invalid mapping",
0521: null, (Throwable) errors.get(0));
0522: }
0523: add(doc);
0524: return this ;
0525: } catch (DocumentException e) {
0526: throw new InvalidMappingException("input stream", null, e);
0527: } finally {
0528: try {
0529: xmlInputStream.close();
0530: } catch (IOException ioe) {
0531: log.warn("Could not close input stream", ioe);
0532: }
0533: }
0534: }
0535:
0536: /**
0537: * Read mappings as a application resource (i.e. classpath lookup).
0538: *
0539: * @param resourceName The resource name
0540: * @param classLoader The class loader to use.
0541: * @return this (for method chaining purposes)
0542: * @throws MappingException Indicates problems locating the resource or
0543: * processing the contained mapping document.
0544: */
0545: public Configuration addResource(String resourceName,
0546: ClassLoader classLoader) throws MappingException {
0547: log.info("Reading mappings from resource: " + resourceName);
0548: InputStream rsrc = classLoader
0549: .getResourceAsStream(resourceName);
0550: if (rsrc == null) {
0551: throw new MappingNotFoundException("resource", resourceName);
0552: }
0553: try {
0554: return addInputStream(rsrc);
0555: } catch (MappingException me) {
0556: throw new InvalidMappingException("resource", resourceName,
0557: me);
0558: }
0559: }
0560:
0561: /**
0562: * Read mappings as a application resourceName (i.e. classpath lookup)
0563: * trying different classloaders.
0564: *
0565: * @param resourceName The resource name
0566: * @return this (for method chaining purposes)
0567: * @throws MappingException Indicates problems locating the resource or
0568: * processing the contained mapping document.
0569: */
0570: public Configuration addResource(String resourceName)
0571: throws MappingException {
0572: log.info("Reading mappings from resource : " + resourceName);
0573: ClassLoader contextClassLoader = Thread.currentThread()
0574: .getContextClassLoader();
0575: InputStream rsrc = null;
0576: if (contextClassLoader != null) {
0577: rsrc = contextClassLoader.getResourceAsStream(resourceName);
0578: }
0579: if (rsrc == null) {
0580: rsrc = Environment.class.getClassLoader()
0581: .getResourceAsStream(resourceName);
0582: }
0583: if (rsrc == null) {
0584: throw new MappingNotFoundException("resource", resourceName);
0585: }
0586: try {
0587: return addInputStream(rsrc);
0588: } catch (MappingException me) {
0589: throw new InvalidMappingException("resource", resourceName,
0590: me);
0591: }
0592: }
0593:
0594: /**
0595: * Read a mapping as an application resouurce using the convention that a class
0596: * named <tt>foo.bar.Foo</tt> is mapped by a file <tt>foo/bar/Foo.hbm.xml</tt>
0597: * which can be resolved as a classpath resource.
0598: *
0599: * @param persistentClass The mapped class
0600: * @return this (for method chaining purposes)
0601: * @throws MappingException Indicates problems locating the resource or
0602: * processing the contained mapping document.
0603: */
0604: public Configuration addClass(Class persistentClass)
0605: throws MappingException {
0606: String mappingResourceName = persistentClass.getName().replace(
0607: '.', '/')
0608: + ".hbm.xml";
0609: log.info("Reading mappings from resource: "
0610: + mappingResourceName);
0611: return addResource(mappingResourceName, persistentClass
0612: .getClassLoader());
0613: }
0614:
0615: /**
0616: * Read all mappings from a jar file
0617: * <p/>
0618: * Assumes that any file named <tt>*.hbm.xml</tt> is a mapping document.
0619: *
0620: * @param jar a jar file
0621: * @return this (for method chaining purposes)
0622: * @throws MappingException Indicates problems reading the jar file or
0623: * processing the contained mapping documents.
0624: */
0625: public Configuration addJar(File jar) throws MappingException {
0626: log.info("Searching for mapping documents in jar: "
0627: + jar.getName());
0628: JarFile jarFile = null;
0629: try {
0630: try {
0631: jarFile = new JarFile(jar);
0632: } catch (IOException ioe) {
0633: throw new InvalidMappingException(
0634: "Could not read mapping documents from jar: "
0635: + jar.getName(), "jar", jar.getName(),
0636: ioe);
0637: }
0638: Enumeration jarEntries = jarFile.entries();
0639: while (jarEntries.hasMoreElements()) {
0640: ZipEntry ze = (ZipEntry) jarEntries.nextElement();
0641: if (ze.getName().endsWith(".hbm.xml")) {
0642: log.info("Found mapping document in jar: "
0643: + ze.getName());
0644: try {
0645: addInputStream(jarFile.getInputStream(ze));
0646: } catch (Exception e) {
0647: throw new InvalidMappingException(
0648: "Could not read mapping documents from jar: "
0649: + jar.getName(), "jar", jar
0650: .getName(), e);
0651: }
0652: }
0653: }
0654: } finally {
0655: try {
0656: if (jarFile != null) {
0657: jarFile.close();
0658: }
0659: } catch (IOException ioe) {
0660: log.error("could not close jar", ioe);
0661: }
0662: }
0663:
0664: return this ;
0665: }
0666:
0667: /**
0668: * Read all mapping documents from a directory tree.
0669: * <p/>
0670: * Assumes that any file named <tt>*.hbm.xml</tt> is a mapping document.
0671: *
0672: * @param dir The directory
0673: * @return this (for method chaining purposes)
0674: * @throws MappingException Indicates problems reading the jar file or
0675: * processing the contained mapping documents.
0676: */
0677: public Configuration addDirectory(File dir) throws MappingException {
0678: File[] files = dir.listFiles();
0679: for (int i = 0; i < files.length; i++) {
0680: if (files[i].isDirectory()) {
0681: addDirectory(files[i]);
0682: } else if (files[i].getName().endsWith(".hbm.xml")) {
0683: addFile(files[i]);
0684: }
0685: }
0686: return this ;
0687: }
0688:
0689: protected void add(org.dom4j.Document doc) throws MappingException {
0690: HbmBinder.bindRoot(doc, createMappings(),
0691: CollectionHelper.EMPTY_MAP);
0692: }
0693:
0694: /**
0695: * Create a new <tt>Mappings</tt> to add class and collection
0696: * mappings to.
0697: */
0698: public Mappings createMappings() {
0699: return new Mappings(classes, collections, tables, namedQueries,
0700: namedSqlQueries, sqlResultSetMappings, imports,
0701: secondPasses, propertyReferences, namingStrategy,
0702: typeDefs, filterDefinitions, extendsQueue,
0703: auxiliaryDatabaseObjects, tableNameBinding,
0704: columnNameBindingPerTable);
0705: }
0706:
0707: private Iterator iterateGenerators(Dialect dialect)
0708: throws MappingException {
0709:
0710: TreeMap generators = new TreeMap();
0711: String defaultCatalog = properties
0712: .getProperty(Environment.DEFAULT_CATALOG);
0713: String defaultSchema = properties
0714: .getProperty(Environment.DEFAULT_SCHEMA);
0715:
0716: Iterator iter = classes.values().iterator();
0717: while (iter.hasNext()) {
0718: PersistentClass pc = (PersistentClass) iter.next();
0719:
0720: if (!pc.isInherited()) {
0721:
0722: IdentifierGenerator ig = pc.getIdentifier()
0723: .createIdentifierGenerator(dialect,
0724: defaultCatalog, defaultSchema,
0725: (RootClass) pc);
0726:
0727: if (ig instanceof PersistentIdentifierGenerator) {
0728: generators.put(((PersistentIdentifierGenerator) ig)
0729: .generatorKey(), ig);
0730: }
0731:
0732: }
0733: }
0734:
0735: iter = collections.values().iterator();
0736: while (iter.hasNext()) {
0737: Collection collection = (Collection) iter.next();
0738:
0739: if (collection.isIdentified()) {
0740:
0741: IdentifierGenerator ig = ((IdentifierCollection) collection)
0742: .getIdentifier().createIdentifierGenerator(
0743: dialect, defaultCatalog, defaultSchema,
0744: null);
0745:
0746: if (ig instanceof PersistentIdentifierGenerator) {
0747: generators.put(((PersistentIdentifierGenerator) ig)
0748: .generatorKey(), ig);
0749: }
0750:
0751: }
0752: }
0753:
0754: return generators.values().iterator();
0755: }
0756:
0757: /**
0758: * Generate DDL for dropping tables
0759: *
0760: * @see org.hibernate.tool.hbm2ddl.SchemaExport
0761: */
0762: public String[] generateDropSchemaScript(Dialect dialect)
0763: throws HibernateException {
0764:
0765: secondPassCompile();
0766:
0767: String defaultCatalog = properties
0768: .getProperty(Environment.DEFAULT_CATALOG);
0769: String defaultSchema = properties
0770: .getProperty(Environment.DEFAULT_SCHEMA);
0771:
0772: ArrayList script = new ArrayList(50);
0773:
0774: // drop them in reverse order in case db needs it done that way...
0775: ListIterator itr = auxiliaryDatabaseObjects
0776: .listIterator(auxiliaryDatabaseObjects.size());
0777: while (itr.hasPrevious()) {
0778: AuxiliaryDatabaseObject object = (AuxiliaryDatabaseObject) itr
0779: .previous();
0780: if (object.appliesToDialect(dialect)) {
0781: script.add(object.sqlDropString(dialect,
0782: defaultCatalog, defaultSchema));
0783: }
0784: }
0785:
0786: if (dialect.dropConstraints()) {
0787: Iterator iter = getTableMappings();
0788: while (iter.hasNext()) {
0789: Table table = (Table) iter.next();
0790: if (table.isPhysicalTable()) {
0791: Iterator subIter = table.getForeignKeyIterator();
0792: while (subIter.hasNext()) {
0793: ForeignKey fk = (ForeignKey) subIter.next();
0794: if (fk.isPhysicalConstraint()) {
0795: script.add(fk.sqlDropString(dialect,
0796: defaultCatalog, defaultSchema));
0797: }
0798: }
0799: }
0800: }
0801: }
0802:
0803: Iterator iter = getTableMappings();
0804: while (iter.hasNext()) {
0805:
0806: Table table = (Table) iter.next();
0807: if (table.isPhysicalTable()) {
0808:
0809: /*Iterator subIter = table.getIndexIterator();
0810: while ( subIter.hasNext() ) {
0811: Index index = (Index) subIter.next();
0812: if ( !index.isForeignKey() || !dialect.hasImplicitIndexForForeignKey() ) {
0813: script.add( index.sqlDropString(dialect) );
0814: }
0815: }*/
0816:
0817: script.add(table.sqlDropString(dialect, defaultCatalog,
0818: defaultSchema));
0819:
0820: }
0821:
0822: }
0823:
0824: iter = iterateGenerators(dialect);
0825: while (iter.hasNext()) {
0826: String[] lines = ((PersistentIdentifierGenerator) iter
0827: .next()).sqlDropStrings(dialect);
0828: for (int i = 0; i < lines.length; i++) {
0829: script.add(lines[i]);
0830: }
0831: }
0832:
0833: return ArrayHelper.toStringArray(script);
0834: }
0835:
0836: /**
0837: * Generate DDL for creating tables
0838: *
0839: * @see org.hibernate.tool.hbm2ddl.SchemaExport
0840: */
0841: public String[] generateSchemaCreationScript(Dialect dialect)
0842: throws HibernateException {
0843: secondPassCompile();
0844:
0845: ArrayList script = new ArrayList(50);
0846: String defaultCatalog = properties
0847: .getProperty(Environment.DEFAULT_CATALOG);
0848: String defaultSchema = properties
0849: .getProperty(Environment.DEFAULT_SCHEMA);
0850:
0851: Iterator iter = getTableMappings();
0852: while (iter.hasNext()) {
0853: Table table = (Table) iter.next();
0854: if (table.isPhysicalTable()) {
0855: script.add(table.sqlCreateString(dialect, mapping,
0856: defaultCatalog, defaultSchema));
0857: Iterator comments = table.sqlCommentStrings(dialect,
0858: defaultCatalog, defaultSchema);
0859: while (comments.hasNext()) {
0860: script.add(comments.next());
0861: }
0862: }
0863: }
0864:
0865: iter = getTableMappings();
0866: while (iter.hasNext()) {
0867: Table table = (Table) iter.next();
0868: if (table.isPhysicalTable()) {
0869:
0870: if (!dialect
0871: .supportsUniqueConstraintInCreateAlterTable()) {
0872: Iterator subIter = table.getUniqueKeyIterator();
0873: while (subIter.hasNext()) {
0874: UniqueKey uk = (UniqueKey) subIter.next();
0875: String constraintString = uk.sqlCreateString(
0876: dialect, mapping, defaultCatalog,
0877: defaultSchema);
0878: if (constraintString != null)
0879: script.add(constraintString);
0880: }
0881: }
0882:
0883: Iterator subIter = table.getIndexIterator();
0884: while (subIter.hasNext()) {
0885: Index index = (Index) subIter.next();
0886: script.add(index.sqlCreateString(dialect, mapping,
0887: defaultCatalog, defaultSchema));
0888: }
0889:
0890: if (dialect.hasAlterTable()) {
0891: subIter = table.getForeignKeyIterator();
0892: while (subIter.hasNext()) {
0893: ForeignKey fk = (ForeignKey) subIter.next();
0894: if (fk.isPhysicalConstraint()) {
0895: script.add(fk.sqlCreateString(dialect,
0896: mapping, defaultCatalog,
0897: defaultSchema));
0898: }
0899: }
0900: }
0901:
0902: }
0903: }
0904:
0905: iter = iterateGenerators(dialect);
0906: while (iter.hasNext()) {
0907: String[] lines = ((PersistentIdentifierGenerator) iter
0908: .next()).sqlCreateStrings(dialect);
0909: for (int i = 0; i < lines.length; i++) {
0910: script.add(lines[i]);
0911: }
0912: }
0913:
0914: Iterator itr = auxiliaryDatabaseObjects.iterator();
0915: while (itr.hasNext()) {
0916: AuxiliaryDatabaseObject object = (AuxiliaryDatabaseObject) itr
0917: .next();
0918: if (object.appliesToDialect(dialect)) {
0919: script.add(object.sqlCreateString(dialect, mapping,
0920: defaultCatalog, defaultSchema));
0921: }
0922: }
0923:
0924: return ArrayHelper.toStringArray(script);
0925: }
0926:
0927: /**
0928: * Generate DDL for altering tables
0929: *
0930: * @see org.hibernate.tool.hbm2ddl.SchemaUpdate
0931: */
0932: public String[] generateSchemaUpdateScript(Dialect dialect,
0933: DatabaseMetadata databaseMetadata)
0934: throws HibernateException {
0935: secondPassCompile();
0936:
0937: String defaultCatalog = properties
0938: .getProperty(Environment.DEFAULT_CATALOG);
0939: String defaultSchema = properties
0940: .getProperty(Environment.DEFAULT_SCHEMA);
0941:
0942: ArrayList script = new ArrayList(50);
0943:
0944: Iterator iter = getTableMappings();
0945: while (iter.hasNext()) {
0946: Table table = (Table) iter.next();
0947: if (table.isPhysicalTable()) {
0948:
0949: TableMetadata tableInfo = databaseMetadata
0950: .getTableMetadata(table.getName(), (table
0951: .getSchema() == null) ? defaultSchema
0952: : table.getSchema(), (table
0953: .getCatalog() == null) ? defaultCatalog
0954: : table.getCatalog(), table.isQuoted()
0955:
0956: );
0957: if (tableInfo == null) {
0958: script.add(table.sqlCreateString(dialect, mapping,
0959: defaultCatalog, defaultSchema));
0960: } else {
0961: Iterator subiter = table.sqlAlterStrings(dialect,
0962: mapping, tableInfo, defaultCatalog,
0963: defaultSchema);
0964: while (subiter.hasNext()) {
0965: script.add(subiter.next());
0966: }
0967: }
0968:
0969: Iterator comments = table.sqlCommentStrings(dialect,
0970: defaultCatalog, defaultSchema);
0971: while (comments.hasNext()) {
0972: script.add(comments.next());
0973: }
0974:
0975: }
0976: }
0977:
0978: iter = getTableMappings();
0979: while (iter.hasNext()) {
0980: Table table = (Table) iter.next();
0981: if (table.isPhysicalTable()) {
0982:
0983: TableMetadata tableInfo = databaseMetadata
0984: .getTableMetadata(table.getName(), table
0985: .getSchema(), table.getCatalog(), table
0986: .isQuoted());
0987:
0988: if (dialect.hasAlterTable()) {
0989: Iterator subIter = table.getForeignKeyIterator();
0990: while (subIter.hasNext()) {
0991: ForeignKey fk = (ForeignKey) subIter.next();
0992: if (fk.isPhysicalConstraint()) {
0993: boolean create = tableInfo == null
0994: || (tableInfo
0995: .getForeignKeyMetadata(fk
0996: .getName()) == null && (
0997: //Icky workaround for MySQL bug:
0998: !(dialect instanceof MySQLDialect) || tableInfo
0999: .getIndexMetadata(fk
1000: .getName()) == null));
1001: if (create) {
1002: script.add(fk.sqlCreateString(dialect,
1003: mapping, defaultCatalog,
1004: defaultSchema));
1005: }
1006: }
1007: }
1008: }
1009:
1010: }
1011:
1012: /*//broken, 'cos we don't generate these with names in SchemaExport
1013: subIter = table.getIndexIterator();
1014: while ( subIter.hasNext() ) {
1015: Index index = (Index) subIter.next();
1016: if ( !index.isForeignKey() || !dialect.hasImplicitIndexForForeignKey() ) {
1017: if ( tableInfo==null || tableInfo.getIndexMetadata( index.getFilterName() ) == null ) {
1018: script.add( index.sqlCreateString(dialect, mapping) );
1019: }
1020: }
1021: }
1022: //broken, 'cos we don't generate these with names in SchemaExport
1023: subIter = table.getUniqueKeyIterator();
1024: while ( subIter.hasNext() ) {
1025: UniqueKey uk = (UniqueKey) subIter.next();
1026: if ( tableInfo==null || tableInfo.getIndexMetadata( uk.getFilterName() ) == null ) {
1027: script.add( uk.sqlCreateString(dialect, mapping) );
1028: }
1029: }*/
1030: }
1031:
1032: iter = iterateGenerators(dialect);
1033: while (iter.hasNext()) {
1034: PersistentIdentifierGenerator generator = (PersistentIdentifierGenerator) iter
1035: .next();
1036: Object key = generator.generatorKey();
1037: if (!databaseMetadata.isSequence(key)
1038: && !databaseMetadata.isTable(key)) {
1039: String[] lines = generator.sqlCreateStrings(dialect);
1040: for (int i = 0; i < lines.length; i++) {
1041: script.add(lines[i]);
1042: }
1043: }
1044: }
1045:
1046: return ArrayHelper.toStringArray(script);
1047: }
1048:
1049: public void validateSchema(Dialect dialect,
1050: DatabaseMetadata databaseMetadata)
1051: throws HibernateException {
1052: secondPassCompile();
1053:
1054: String defaultCatalog = properties
1055: .getProperty(Environment.DEFAULT_CATALOG);
1056: String defaultSchema = properties
1057: .getProperty(Environment.DEFAULT_SCHEMA);
1058:
1059: Iterator iter = getTableMappings();
1060: while (iter.hasNext()) {
1061: Table table = (Table) iter.next();
1062: if (table.isPhysicalTable()) {
1063:
1064: TableMetadata tableInfo = databaseMetadata
1065: .getTableMetadata(table.getName(), (table
1066: .getSchema() == null) ? defaultSchema
1067: : table.getSchema(), (table
1068: .getCatalog() == null) ? defaultCatalog
1069: : table.getCatalog(), table.isQuoted());
1070: if (tableInfo == null) {
1071: throw new HibernateException("Missing table: "
1072: + table.getName());
1073: } else {
1074: table.validateColumns(dialect, mapping, tableInfo);
1075: }
1076:
1077: }
1078: }
1079:
1080: iter = iterateGenerators(dialect);
1081: while (iter.hasNext()) {
1082: PersistentIdentifierGenerator generator = (PersistentIdentifierGenerator) iter
1083: .next();
1084: Object key = generator.generatorKey();
1085: if (!databaseMetadata.isSequence(key)
1086: && !databaseMetadata.isTable(key)) {
1087: throw new HibernateException(
1088: "Missing sequence or table: " + key);
1089: }
1090: }
1091: }
1092:
1093: private void validate() throws MappingException {
1094: Iterator iter = classes.values().iterator();
1095: while (iter.hasNext()) {
1096: ((PersistentClass) iter.next()).validate(mapping);
1097: }
1098: iter = collections.values().iterator();
1099: while (iter.hasNext()) {
1100: ((Collection) iter.next()).validate(mapping);
1101: }
1102: }
1103:
1104: /**
1105: * Call this to ensure the mappings are fully compiled/built. Usefull to ensure getting
1106: * access to all information in the metamodel when calling e.g. getClassMappings().
1107: */
1108: public void buildMappings() {
1109: secondPassCompile();
1110: }
1111:
1112: // This method may be called many times!!
1113: protected void secondPassCompile() throws MappingException {
1114: log.debug("processing extends queue");
1115:
1116: processExtendsQueue();
1117:
1118: log.debug("processing collection mappings");
1119:
1120: Iterator iter = secondPasses.iterator();
1121: while (iter.hasNext()) {
1122: SecondPass sp = (SecondPass) iter.next();
1123: if (!(sp instanceof QuerySecondPass)) {
1124: sp.doSecondPass(classes);
1125: iter.remove();
1126: }
1127: }
1128:
1129: log
1130: .debug("processing native query and ResultSetMapping mappings");
1131: iter = secondPasses.iterator();
1132: while (iter.hasNext()) {
1133: SecondPass sp = (SecondPass) iter.next();
1134: sp.doSecondPass(classes);
1135: iter.remove();
1136: }
1137:
1138: log.debug("processing association property references");
1139:
1140: iter = propertyReferences.iterator();
1141: while (iter.hasNext()) {
1142: Mappings.PropertyReference upr = (Mappings.PropertyReference) iter
1143: .next();
1144:
1145: PersistentClass clazz = getClassMapping(upr.referencedClass);
1146: if (clazz == null) {
1147: throw new MappingException(
1148: "property-ref to unmapped class: "
1149: + upr.referencedClass);
1150: }
1151:
1152: Property prop = clazz
1153: .getReferencedProperty(upr.propertyName);
1154: if (upr.unique) {
1155: ((SimpleValue) prop.getValue())
1156: .setAlternateUniqueKey(true);
1157: }
1158: }
1159:
1160: //TODO: Somehow add the newly created foreign keys to the internal collection
1161:
1162: log.debug("processing foreign key constraints");
1163:
1164: iter = getTableMappings();
1165: Set done = new HashSet();
1166: while (iter.hasNext()) {
1167: secondPassCompileForeignKeys((Table) iter.next(), done);
1168: }
1169:
1170: }
1171:
1172: /**
1173: * Try to empty the extends queue.
1174: */
1175: private void processExtendsQueue() {
1176: // todo : would love to have this work on a notification basis
1177: // where the successful binding of an entity/subclass would
1178: // emit a notification which the extendsQueue entries could
1179: // react to...
1180: org.dom4j.Document document = findPossibleExtends();
1181: while (document != null) {
1182: add(document);
1183: document = findPossibleExtends();
1184: }
1185:
1186: if (extendsQueue.size() > 0) {
1187: // Iterator iterator = extendsQueue.iterator();
1188: Iterator iterator = extendsQueue.keySet().iterator();
1189: StringBuffer buf = new StringBuffer(
1190: "Following superclasses referenced in extends not found: ");
1191: while (iterator.hasNext()) {
1192: final ExtendsQueueEntry entry = (ExtendsQueueEntry) iterator
1193: .next();
1194: buf.append(entry.getExplicitName());
1195: if (entry.getMappingPackage() != null) {
1196: buf.append("[").append(entry.getMappingPackage())
1197: .append("]");
1198: }
1199: if (iterator.hasNext()) {
1200: buf.append(",");
1201: }
1202: }
1203: throw new MappingException(buf.toString());
1204: }
1205: }
1206:
1207: /**
1208: * Find the first possible element in the queue of extends.
1209: */
1210: protected org.dom4j.Document findPossibleExtends() {
1211: // Iterator iter = extendsQueue.iterator();
1212: Iterator iter = extendsQueue.keySet().iterator();
1213: while (iter.hasNext()) {
1214: final ExtendsQueueEntry entry = (ExtendsQueueEntry) iter
1215: .next();
1216: if (getClassMapping(entry.getExplicitName()) != null) {
1217: // found
1218: iter.remove();
1219: return entry.getDocument();
1220: } else if (getClassMapping(HbmBinder.getClassName(entry
1221: .getExplicitName(), entry.getMappingPackage())) != null) {
1222: // found
1223: iter.remove();
1224: return entry.getDocument();
1225: }
1226: }
1227: return null;
1228: }
1229:
1230: protected void secondPassCompileForeignKeys(Table table, Set done)
1231: throws MappingException {
1232:
1233: table.createForeignKeys();
1234:
1235: Iterator iter = table.getForeignKeyIterator();
1236: while (iter.hasNext()) {
1237:
1238: ForeignKey fk = (ForeignKey) iter.next();
1239: if (!done.contains(fk)) {
1240: done.add(fk);
1241: final String referencedEntityName = fk
1242: .getReferencedEntityName();
1243: if (referencedEntityName == null) {
1244: throw new MappingException(
1245: "An association from the table "
1246: + fk.getTable().getName()
1247: + " does not specify the referenced entity");
1248: }
1249: if (log.isDebugEnabled()) {
1250: log.debug("resolving reference to class: "
1251: + referencedEntityName);
1252: }
1253: PersistentClass referencedClass = (PersistentClass) classes
1254: .get(referencedEntityName);
1255: if (referencedClass == null) {
1256: throw new MappingException(
1257: "An association from the table "
1258: + fk.getTable().getName()
1259: + " refers to an unmapped class: "
1260: + referencedEntityName);
1261: }
1262: if (referencedClass.isJoinedSubclass()) {
1263: secondPassCompileForeignKeys(referencedClass
1264: .getSuperclass().getTable(), done);
1265: }
1266: fk.setReferencedTable(referencedClass.getTable());
1267: fk.alignColumns();
1268: }
1269: }
1270: }
1271:
1272: /**
1273: * Get the named queries
1274: */
1275: public Map getNamedQueries() {
1276: return namedQueries;
1277: }
1278:
1279: /**
1280: * Instantiate a new <tt>SessionFactory</tt>, using the properties and
1281: * mappings in this configuration. The <tt>SessionFactory</tt> will be
1282: * immutable, so changes made to the <tt>Configuration</tt> after
1283: * building the <tt>SessionFactory</tt> will not affect it.
1284: *
1285: * @return a new factory for <tt>Session</tt>s
1286: * @see org.hibernate.SessionFactory
1287: */
1288: public SessionFactory buildSessionFactory()
1289: throws HibernateException {
1290: log.debug("Preparing to build session factory with filters : "
1291: + filterDefinitions);
1292: secondPassCompile();
1293: validate();
1294: Environment.verifyProperties(properties);
1295: Properties copy = new Properties();
1296: copy.putAll(properties);
1297: PropertiesHelper.resolvePlaceHolders(copy);
1298: Settings settings = buildSettings(copy);
1299:
1300: return new SessionFactoryImpl(this , mapping, settings,
1301: getInitializedEventListeners());
1302: }
1303:
1304: private EventListeners getInitializedEventListeners() {
1305: EventListeners result = (EventListeners) eventListeners
1306: .shallowCopy();
1307: result.initializeListeners(this );
1308: return result;
1309: }
1310:
1311: /**
1312: * Return the configured <tt>Interceptor</tt>
1313: */
1314: public Interceptor getInterceptor() {
1315: return interceptor;
1316: }
1317:
1318: /**
1319: * Get all properties
1320: */
1321: public Properties getProperties() {
1322: return properties;
1323: }
1324:
1325: /**
1326: * Configure an <tt>Interceptor</tt>
1327: */
1328: public Configuration setInterceptor(Interceptor interceptor) {
1329: this .interceptor = interceptor;
1330: return this ;
1331: }
1332:
1333: /**
1334: * Specify a completely new set of properties
1335: */
1336: public Configuration setProperties(Properties properties) {
1337: this .properties = properties;
1338: return this ;
1339: }
1340:
1341: /**
1342: * Set the given properties
1343: */
1344: public Configuration addProperties(Properties extraProperties) {
1345: this .properties.putAll(extraProperties);
1346: return this ;
1347: }
1348:
1349: /**
1350: * Adds the incoming properties to the internap properties structure,
1351: * as long as the internal structure does not already contain an
1352: * entry for the given key.
1353: *
1354: * @param properties
1355: * @return this
1356: */
1357: public Configuration mergeProperties(Properties properties) {
1358: Iterator itr = properties.entrySet().iterator();
1359: while (itr.hasNext()) {
1360: final Map.Entry entry = (Map.Entry) itr.next();
1361: if (this .properties.containsKey(entry.getKey())) {
1362: continue;
1363: }
1364: this .properties.setProperty((String) entry.getKey(),
1365: (String) entry.getValue());
1366: }
1367: return this ;
1368: }
1369:
1370: /**
1371: * Set a property
1372: */
1373: public Configuration setProperty(String propertyName, String value) {
1374: properties.setProperty(propertyName, value);
1375: return this ;
1376: }
1377:
1378: /**
1379: * Get a property
1380: */
1381: public String getProperty(String propertyName) {
1382: return properties.getProperty(propertyName);
1383: }
1384:
1385: private void addProperties(Element parent) {
1386: Iterator iter = parent.elementIterator("property");
1387: while (iter.hasNext()) {
1388: Element node = (Element) iter.next();
1389: String name = node.attributeValue("name");
1390: String value = node.getText().trim();
1391: log.debug(name + "=" + value);
1392: properties.setProperty(name, value);
1393: if (!name.startsWith("hibernate")) {
1394: properties.setProperty("hibernate." + name, value);
1395: }
1396: }
1397: Environment.verifyProperties(properties);
1398: }
1399:
1400: /**
1401: * Get the configuration file as an <tt>InputStream</tt>. Might be overridden
1402: * by subclasses to allow the configuration to be located by some arbitrary
1403: * mechanism.
1404: */
1405: protected InputStream getConfigurationInputStream(String resource)
1406: throws HibernateException {
1407:
1408: log.info("Configuration resource: " + resource);
1409:
1410: return ConfigHelper.getResourceAsStream(resource);
1411:
1412: }
1413:
1414: /**
1415: * Use the mappings and properties specified in an application
1416: * resource named <tt>hibernate.cfg.xml</tt>.
1417: */
1418: public Configuration configure() throws HibernateException {
1419: configure("/hibernate.cfg.xml");
1420: return this ;
1421: }
1422:
1423: /**
1424: * Use the mappings and properties specified in the given application
1425: * resource. The format of the resource is defined in
1426: * <tt>hibernate-configuration-3.0.dtd</tt>.
1427: * <p/>
1428: * The resource is found via <tt>getConfigurationInputStream(resource)</tt>.
1429: */
1430: public Configuration configure(String resource)
1431: throws HibernateException {
1432: log.info("configuring from resource: " + resource);
1433: InputStream stream = getConfigurationInputStream(resource);
1434: return doConfigure(stream, resource);
1435: }
1436:
1437: /**
1438: * Use the mappings and properties specified in the given document.
1439: * The format of the document is defined in
1440: * <tt>hibernate-configuration-3.0.dtd</tt>.
1441: *
1442: * @param url URL from which you wish to load the configuration
1443: * @return A configuration configured via the file
1444: * @throws HibernateException
1445: */
1446: public Configuration configure(URL url) throws HibernateException {
1447: log.info("configuring from url: " + url.toString());
1448: try {
1449: return doConfigure(url.openStream(), url.toString());
1450: } catch (IOException ioe) {
1451: throw new HibernateException(
1452: "could not configure from URL: " + url, ioe);
1453: }
1454: }
1455:
1456: /**
1457: * Use the mappings and properties specified in the given application
1458: * file. The format of the file is defined in
1459: * <tt>hibernate-configuration-3.0.dtd</tt>.
1460: *
1461: * @param configFile <tt>File</tt> from which you wish to load the configuration
1462: * @return A configuration configured via the file
1463: * @throws HibernateException
1464: */
1465: public Configuration configure(File configFile)
1466: throws HibernateException {
1467: log.info("configuring from file: " + configFile.getName());
1468: try {
1469: return doConfigure(new FileInputStream(configFile),
1470: configFile.toString());
1471: } catch (FileNotFoundException fnfe) {
1472: throw new HibernateException("could not find file: "
1473: + configFile, fnfe);
1474: }
1475: }
1476:
1477: /**
1478: * Use the mappings and properties specified in the given application
1479: * resource. The format of the resource is defined in
1480: * <tt>hibernate-configuration-3.0.dtd</tt>.
1481: *
1482: * @param stream Inputstream to be read from
1483: * @param resourceName The name to use in warning/error messages
1484: * @return A configuration configured via the stream
1485: * @throws HibernateException
1486: */
1487: protected Configuration doConfigure(InputStream stream,
1488: String resourceName) throws HibernateException {
1489:
1490: org.dom4j.Document doc;
1491: try {
1492: List errors = new ArrayList();
1493: doc = xmlHelper.createSAXReader(resourceName, errors,
1494: entityResolver).read(new InputSource(stream));
1495: if (errors.size() != 0) {
1496: throw new MappingException("invalid configuration",
1497: (Throwable) errors.get(0));
1498: }
1499: } catch (DocumentException e) {
1500: throw new HibernateException(
1501: "Could not parse configuration: " + resourceName, e);
1502: } finally {
1503: try {
1504: stream.close();
1505: } catch (IOException ioe) {
1506: log.warn("could not close input stream for: "
1507: + resourceName, ioe);
1508: }
1509: }
1510:
1511: return doConfigure(doc);
1512:
1513: }
1514:
1515: /**
1516: * Use the mappings and properties specified in the given XML document.
1517: * The format of the file is defined in
1518: * <tt>hibernate-configuration-3.0.dtd</tt>.
1519: *
1520: * @param document an XML document from which you wish to load the configuration
1521: * @return A configuration configured via the <tt>Document</tt>
1522: * @throws HibernateException if there is problem in accessing the file.
1523: */
1524: public Configuration configure(Document document)
1525: throws HibernateException {
1526: log.info("configuring from XML document");
1527: return doConfigure(xmlHelper.createDOMReader().read(document));
1528: }
1529:
1530: protected Configuration doConfigure(org.dom4j.Document doc)
1531: throws HibernateException {
1532:
1533: Element sfNode = doc.getRootElement()
1534: .element("session-factory");
1535: String name = sfNode.attributeValue("name");
1536: if (name != null) {
1537: properties.setProperty(Environment.SESSION_FACTORY_NAME,
1538: name);
1539: }
1540: addProperties(sfNode);
1541: parseSessionFactory(sfNode, name);
1542:
1543: Element secNode = doc.getRootElement().element("security");
1544: if (secNode != null) {
1545: parseSecurity(secNode);
1546: }
1547:
1548: log.info("Configured SessionFactory: " + name);
1549: log.debug("properties: " + properties);
1550:
1551: return this ;
1552:
1553: }
1554:
1555: private void parseSessionFactory(Element sfNode, String name) {
1556: Iterator elements = sfNode.elementIterator();
1557: while (elements.hasNext()) {
1558: Element subelement = (Element) elements.next();
1559: String subelementName = subelement.getName();
1560: if ("mapping".equals(subelementName)) {
1561: parseMappingElement(subelement, name);
1562: } else if ("class-cache".equals(subelementName)) {
1563: String className = subelement.attributeValue("class");
1564: Attribute regionNode = subelement.attribute("region");
1565: final String region = (regionNode == null) ? className
1566: : regionNode.getValue();
1567: boolean includeLazy = !"non-lazy".equals(subelement
1568: .attributeValue("include"));
1569: setCacheConcurrencyStrategy(className, subelement
1570: .attributeValue("usage"), region, includeLazy);
1571: } else if ("collection-cache".equals(subelementName)) {
1572: String role = subelement.attributeValue("collection");
1573: Attribute regionNode = subelement.attribute("region");
1574: final String region = (regionNode == null) ? role
1575: : regionNode.getValue();
1576: setCollectionCacheConcurrencyStrategy(role, subelement
1577: .attributeValue("usage"), region);
1578: } else if ("listener".equals(subelementName)) {
1579: parseListener(subelement);
1580: } else if ("event".equals(subelementName)) {
1581: parseEvent(subelement);
1582: }
1583: }
1584: }
1585:
1586: protected void parseMappingElement(Element subelement, String name) {
1587: Attribute rsrc = subelement.attribute("resource");
1588: Attribute file = subelement.attribute("file");
1589: Attribute jar = subelement.attribute("jar");
1590: Attribute pkg = subelement.attribute("package");
1591: Attribute clazz = subelement.attribute("class");
1592: if (rsrc != null) {
1593: log.debug(name + "<-" + rsrc);
1594: addResource(rsrc.getValue());
1595: } else if (jar != null) {
1596: log.debug(name + "<-" + jar);
1597: addJar(new File(jar.getValue()));
1598: } else if (pkg != null) {
1599: throw new MappingException(
1600: "An AnnotationConfiguration instance is required to use <mapping package=\""
1601: + pkg.getValue() + "\"/>");
1602: } else if (clazz != null) {
1603: throw new MappingException(
1604: "An AnnotationConfiguration instance is required to use <mapping class=\""
1605: + clazz.getValue() + "\"/>");
1606: } else {
1607: if (file == null) {
1608: throw new MappingException(
1609: "<mapping> element in configuration specifies no attributes");
1610: }
1611: log.debug(name + "<-" + file);
1612: addFile(file.getValue());
1613: }
1614: }
1615:
1616: private void parseSecurity(Element secNode) {
1617: String contextId = secNode.attributeValue("context");
1618: setProperty(Environment.JACC_CONTEXTID, contextId);
1619: log.info("JACC contextID: " + contextId);
1620: JACCConfiguration jcfg = new JACCConfiguration(contextId);
1621: Iterator grantElements = secNode.elementIterator();
1622: while (grantElements.hasNext()) {
1623: Element grantElement = (Element) grantElements.next();
1624: String elementName = grantElement.getName();
1625: if ("grant".equals(elementName)) {
1626: jcfg.addPermission(grantElement.attributeValue("role"),
1627: grantElement.attributeValue("entity-name"),
1628: grantElement.attributeValue("actions"));
1629: }
1630: }
1631: }
1632:
1633: private void parseEvent(Element element) {
1634: String type = element.attributeValue("type");
1635: List listeners = element.elements();
1636: String[] listenerClasses = new String[listeners.size()];
1637: for (int i = 0; i < listeners.size(); i++) {
1638: listenerClasses[i] = ((Element) listeners.get(i))
1639: .attributeValue("class");
1640: }
1641: log.debug("Event listeners: " + type + "="
1642: + StringHelper.toString(listenerClasses));
1643: setListeners(type, listenerClasses);
1644: }
1645:
1646: private void parseListener(Element element) {
1647: String type = element.attributeValue("type");
1648: if (type == null) {
1649: throw new MappingException("No type specified for listener");
1650: }
1651: String impl = element.attributeValue("class");
1652: log.debug("Event listener: " + type + "=" + impl);
1653: setListeners(type, new String[] { impl });
1654: }
1655:
1656: public void setListeners(String type, String[] listenerClasses) {
1657: Object[] listeners = (Object[]) Array.newInstance(
1658: eventListeners.getListenerClassFor(type),
1659: listenerClasses.length);
1660: for (int i = 0; i < listeners.length; i++) {
1661: try {
1662: listeners[i] = ReflectHelper.classForName(
1663: listenerClasses[i]).newInstance();
1664: } catch (Exception e) {
1665: throw new MappingException(
1666: "Unable to instantiate specified event ("
1667: + type + ") listener class: "
1668: + listenerClasses[i], e);
1669: }
1670: }
1671: setListeners(type, listeners);
1672: }
1673:
1674: public void setListener(String type, Object listener) {
1675: if (listener == null) {
1676: setListener(type, null);
1677: } else {
1678: Object[] listeners = (Object[]) Array.newInstance(
1679: eventListeners.getListenerClassFor(type), 1);
1680: listeners[0] = listener;
1681: setListeners(type, listeners);
1682: }
1683: }
1684:
1685: public void setListeners(String type, Object[] listeners) {
1686: if ("auto-flush".equals(type)) {
1687: if (listeners == null) {
1688: eventListeners
1689: .setAutoFlushEventListeners(new AutoFlushEventListener[] {});
1690: } else {
1691: eventListeners
1692: .setAutoFlushEventListeners((AutoFlushEventListener[]) listeners);
1693: }
1694: } else if ("merge".equals(type)) {
1695: if (listeners == null) {
1696: eventListeners
1697: .setMergeEventListeners(new MergeEventListener[] {});
1698: } else {
1699: eventListeners
1700: .setMergeEventListeners((MergeEventListener[]) listeners);
1701: }
1702: } else if ("create".equals(type)) {
1703: if (listeners == null) {
1704: eventListeners
1705: .setPersistEventListeners(new PersistEventListener[] {});
1706: } else {
1707: eventListeners
1708: .setPersistEventListeners((PersistEventListener[]) listeners);
1709: }
1710: } else if ("create-onflush".equals(type)) {
1711: if (listeners == null) {
1712: eventListeners
1713: .setPersistOnFlushEventListeners(new PersistEventListener[] {});
1714: } else {
1715: eventListeners
1716: .setPersistOnFlushEventListeners((PersistEventListener[]) listeners);
1717: }
1718: } else if ("delete".equals(type)) {
1719: if (listeners == null) {
1720: eventListeners
1721: .setDeleteEventListeners(new DeleteEventListener[] {});
1722: } else {
1723: eventListeners
1724: .setDeleteEventListeners((DeleteEventListener[]) listeners);
1725: }
1726: } else if ("dirty-check".equals(type)) {
1727: if (listeners == null) {
1728: eventListeners
1729: .setDirtyCheckEventListeners(new DirtyCheckEventListener[] {});
1730: } else {
1731: eventListeners
1732: .setDirtyCheckEventListeners((DirtyCheckEventListener[]) listeners);
1733: }
1734: } else if ("evict".equals(type)) {
1735: if (listeners == null) {
1736: eventListeners
1737: .setEvictEventListeners(new EvictEventListener[] {});
1738: } else {
1739: eventListeners
1740: .setEvictEventListeners((EvictEventListener[]) listeners);
1741: }
1742: } else if ("flush".equals(type)) {
1743: if (listeners == null) {
1744: eventListeners
1745: .setFlushEventListeners(new FlushEventListener[] {});
1746: } else {
1747: eventListeners
1748: .setFlushEventListeners((FlushEventListener[]) listeners);
1749: }
1750: } else if ("flush-entity".equals(type)) {
1751: if (listeners == null) {
1752: eventListeners
1753: .setFlushEntityEventListeners(new FlushEntityEventListener[] {});
1754: } else {
1755: eventListeners
1756: .setFlushEntityEventListeners((FlushEntityEventListener[]) listeners);
1757: }
1758: } else if ("load".equals(type)) {
1759: if (listeners == null) {
1760: eventListeners
1761: .setLoadEventListeners(new LoadEventListener[] {});
1762: } else {
1763: eventListeners
1764: .setLoadEventListeners((LoadEventListener[]) listeners);
1765: }
1766: } else if ("load-collection".equals(type)) {
1767: if (listeners == null) {
1768: eventListeners
1769: .setInitializeCollectionEventListeners(new InitializeCollectionEventListener[] {});
1770: } else {
1771: eventListeners
1772: .setInitializeCollectionEventListeners((InitializeCollectionEventListener[]) listeners);
1773: }
1774: } else if ("lock".equals(type)) {
1775: if (listeners == null) {
1776: eventListeners
1777: .setLockEventListeners(new LockEventListener[] {});
1778: } else {
1779: eventListeners
1780: .setLockEventListeners((LockEventListener[]) listeners);
1781: }
1782: } else if ("refresh".equals(type)) {
1783: if (listeners == null) {
1784: eventListeners
1785: .setRefreshEventListeners(new RefreshEventListener[] {});
1786: } else {
1787: eventListeners
1788: .setRefreshEventListeners((RefreshEventListener[]) listeners);
1789: }
1790: } else if ("replicate".equals(type)) {
1791: if (listeners == null) {
1792: eventListeners
1793: .setReplicateEventListeners(new ReplicateEventListener[] {});
1794: } else {
1795: eventListeners
1796: .setReplicateEventListeners((ReplicateEventListener[]) listeners);
1797: }
1798: } else if ("save-update".equals(type)) {
1799: if (listeners == null) {
1800: eventListeners
1801: .setSaveOrUpdateEventListeners(new SaveOrUpdateEventListener[] {});
1802: } else {
1803: eventListeners
1804: .setSaveOrUpdateEventListeners((SaveOrUpdateEventListener[]) listeners);
1805: }
1806: } else if ("save".equals(type)) {
1807: if (listeners == null) {
1808: eventListeners
1809: .setSaveEventListeners(new SaveOrUpdateEventListener[] {});
1810: } else {
1811: eventListeners
1812: .setSaveEventListeners((SaveOrUpdateEventListener[]) listeners);
1813: }
1814: } else if ("update".equals(type)) {
1815: if (listeners == null) {
1816: eventListeners
1817: .setUpdateEventListeners(new SaveOrUpdateEventListener[] {});
1818: } else {
1819: eventListeners
1820: .setUpdateEventListeners((SaveOrUpdateEventListener[]) listeners);
1821: }
1822: } else if ("pre-load".equals(type)) {
1823: if (listeners == null) {
1824: eventListeners
1825: .setPreLoadEventListeners(new PreLoadEventListener[] {});
1826: } else {
1827: eventListeners
1828: .setPreLoadEventListeners((PreLoadEventListener[]) listeners);
1829: }
1830: } else if ("pre-update".equals(type)) {
1831: if (listeners == null) {
1832: eventListeners
1833: .setPreUpdateEventListeners(new PreUpdateEventListener[] {});
1834: } else {
1835: eventListeners
1836: .setPreUpdateEventListeners((PreUpdateEventListener[]) listeners);
1837: }
1838: } else if ("pre-delete".equals(type)) {
1839: if (listeners == null) {
1840: eventListeners
1841: .setPreDeleteEventListeners(new PreDeleteEventListener[] {});
1842: } else {
1843: eventListeners
1844: .setPreDeleteEventListeners((PreDeleteEventListener[]) listeners);
1845: }
1846: } else if ("pre-insert".equals(type)) {
1847: if (listeners == null) {
1848: eventListeners
1849: .setPreInsertEventListeners(new PreInsertEventListener[] {});
1850: } else {
1851: eventListeners
1852: .setPreInsertEventListeners((PreInsertEventListener[]) listeners);
1853: }
1854: } else if ("post-load".equals(type)) {
1855: if (listeners == null) {
1856: eventListeners
1857: .setPostLoadEventListeners(new PostLoadEventListener[] {});
1858: } else {
1859: eventListeners
1860: .setPostLoadEventListeners((PostLoadEventListener[]) listeners);
1861: }
1862: } else if ("post-update".equals(type)) {
1863: if (listeners == null) {
1864: eventListeners
1865: .setPostUpdateEventListeners(new PostUpdateEventListener[] {});
1866: } else {
1867: eventListeners
1868: .setPostUpdateEventListeners((PostUpdateEventListener[]) listeners);
1869: }
1870: } else if ("post-delete".equals(type)) {
1871: if (listeners == null) {
1872: eventListeners
1873: .setPostDeleteEventListeners(new PostDeleteEventListener[] {});
1874: } else {
1875: eventListeners
1876: .setPostDeleteEventListeners((PostDeleteEventListener[]) listeners);
1877: }
1878: } else if ("post-insert".equals(type)) {
1879: if (listeners == null) {
1880: eventListeners
1881: .setPostInsertEventListeners(new PostInsertEventListener[] {});
1882: } else {
1883: eventListeners
1884: .setPostInsertEventListeners((PostInsertEventListener[]) listeners);
1885: }
1886: } else if ("post-commit-update".equals(type)) {
1887: if (listeners == null) {
1888: eventListeners
1889: .setPostCommitUpdateEventListeners(new PostUpdateEventListener[] {});
1890: } else {
1891: eventListeners
1892: .setPostCommitUpdateEventListeners((PostUpdateEventListener[]) listeners);
1893: }
1894: } else if ("post-commit-delete".equals(type)) {
1895: if (listeners == null) {
1896: eventListeners
1897: .setPostCommitDeleteEventListeners(new PostDeleteEventListener[] {});
1898: } else {
1899: eventListeners
1900: .setPostCommitDeleteEventListeners((PostDeleteEventListener[]) listeners);
1901: }
1902: } else if ("post-commit-insert".equals(type)) {
1903: if (listeners == null) {
1904: eventListeners
1905: .setPostCommitInsertEventListeners(new PostInsertEventListener[] {});
1906: } else {
1907: eventListeners
1908: .setPostCommitInsertEventListeners((PostInsertEventListener[]) listeners);
1909: }
1910: } else {
1911: log.warn("Unrecognized listener type [" + type + "]");
1912: }
1913: }
1914:
1915: public EventListeners getEventListeners() {
1916: return eventListeners;
1917: }
1918:
1919: RootClass getRootClassMapping(String clazz) throws MappingException {
1920: try {
1921: return (RootClass) getClassMapping(clazz);
1922: } catch (ClassCastException cce) {
1923: throw new MappingException(
1924: "You may only specify a cache for root <class> mappings");
1925: }
1926: }
1927:
1928: /**
1929: * Set up a cache for an entity class
1930: *
1931: * @param clazz
1932: * @param concurrencyStrategy
1933: * @return Configuration
1934: * @throws MappingException
1935: */
1936: public Configuration setCacheConcurrencyStrategy(String clazz,
1937: String concurrencyStrategy) throws MappingException {
1938: setCacheConcurrencyStrategy(clazz, concurrencyStrategy, clazz);
1939: return this ;
1940: }
1941:
1942: public void setCacheConcurrencyStrategy(String clazz,
1943: String concurrencyStrategy, String region)
1944: throws MappingException {
1945: setCacheConcurrencyStrategy(clazz, concurrencyStrategy, region,
1946: true);
1947: }
1948:
1949: void setCacheConcurrencyStrategy(String clazz,
1950: String concurrencyStrategy, String region,
1951: boolean includeLazy) throws MappingException {
1952: RootClass rootClass = getRootClassMapping(clazz);
1953: if (rootClass == null) {
1954: throw new MappingException(
1955: "Cannot cache an unknown entity: " + clazz);
1956: }
1957: rootClass.setCacheConcurrencyStrategy(concurrencyStrategy);
1958: rootClass.setCacheRegionName(region);
1959: rootClass.setLazyPropertiesCacheable(includeLazy);
1960: }
1961:
1962: /**
1963: * Set up a cache for a collection role
1964: *
1965: * @param collectionRole
1966: * @param concurrencyStrategy
1967: * @return Configuration
1968: * @throws MappingException
1969: */
1970: public Configuration setCollectionCacheConcurrencyStrategy(
1971: String collectionRole, String concurrencyStrategy)
1972: throws MappingException {
1973: setCollectionCacheConcurrencyStrategy(collectionRole,
1974: concurrencyStrategy, collectionRole);
1975: return this ;
1976: }
1977:
1978: public void setCollectionCacheConcurrencyStrategy(
1979: String collectionRole, String concurrencyStrategy,
1980: String region) throws MappingException {
1981: Collection collection = getCollectionMapping(collectionRole);
1982: if (collection == null) {
1983: throw new MappingException(
1984: "Cannot cache an unknown collection: "
1985: + collectionRole);
1986: }
1987: collection.setCacheConcurrencyStrategy(concurrencyStrategy);
1988: collection.setCacheRegionName(region);
1989: }
1990:
1991: /**
1992: * Get the query language imports
1993: *
1994: * @return a mapping from "import" names to fully qualified class names
1995: */
1996: public Map getImports() {
1997: return imports;
1998: }
1999:
2000: /**
2001: * Create an object-oriented view of the configuration properties
2002: */
2003: public Settings buildSettings() throws HibernateException {
2004: Properties clone = (Properties) properties.clone();
2005: PropertiesHelper.resolvePlaceHolders(clone);
2006: return settingsFactory.buildSettings(clone);
2007: }
2008:
2009: public Settings buildSettings(Properties props)
2010: throws HibernateException {
2011: return settingsFactory.buildSettings(props);
2012: }
2013:
2014: public Map getNamedSQLQueries() {
2015: return namedSqlQueries;
2016: }
2017:
2018: public Map getSqlResultSetMappings() {
2019: return sqlResultSetMappings;
2020: }
2021:
2022: /**
2023: * @return the NamingStrategy.
2024: */
2025: public NamingStrategy getNamingStrategy() {
2026: return namingStrategy;
2027: }
2028:
2029: /**
2030: * Set a custom naming strategy
2031: *
2032: * @param namingStrategy the NamingStrategy to set
2033: */
2034: public Configuration setNamingStrategy(NamingStrategy namingStrategy) {
2035: this .namingStrategy = namingStrategy;
2036: return this ;
2037: }
2038:
2039: public Mapping buildMapping() {
2040: return new Mapping() {
2041: /**
2042: * Returns the identifier type of a mapped class
2043: */
2044: public Type getIdentifierType(String persistentClass)
2045: throws MappingException {
2046: PersistentClass pc = ((PersistentClass) classes
2047: .get(persistentClass));
2048: if (pc == null) {
2049: throw new MappingException(
2050: "persistent class not known: "
2051: + persistentClass);
2052: }
2053: return pc.getIdentifier().getType();
2054: }
2055:
2056: public String getIdentifierPropertyName(
2057: String persistentClass) throws MappingException {
2058: final PersistentClass pc = (PersistentClass) classes
2059: .get(persistentClass);
2060: if (pc == null) {
2061: throw new MappingException(
2062: "persistent class not known: "
2063: + persistentClass);
2064: }
2065: if (!pc.hasIdentifierProperty()) {
2066: return null;
2067: }
2068: return pc.getIdentifierProperty().getName();
2069: }
2070:
2071: public Type getReferencedPropertyType(
2072: String persistentClass, String propertyName)
2073: throws MappingException {
2074: final PersistentClass pc = (PersistentClass) classes
2075: .get(persistentClass);
2076: if (pc == null) {
2077: throw new MappingException(
2078: "persistent class not known: "
2079: + persistentClass);
2080: }
2081: Property prop = pc.getReferencedProperty(propertyName);
2082: if (prop == null) {
2083: throw new MappingException("property not known: "
2084: + persistentClass + '.' + propertyName);
2085: }
2086: return prop.getType();
2087: }
2088: };
2089: }
2090:
2091: private void readObject(ObjectInputStream ois) throws IOException,
2092: ClassNotFoundException {
2093: ois.defaultReadObject();
2094: this .mapping = buildMapping();
2095: xmlHelper = new XMLHelper();
2096: }
2097:
2098: public Map getFilterDefinitions() {
2099: return filterDefinitions;
2100: }
2101:
2102: public void addFilterDefinition(FilterDefinition definition) {
2103: filterDefinitions.put(definition.getFilterName(), definition);
2104: }
2105:
2106: public void addAuxiliaryDatabaseObject(
2107: AuxiliaryDatabaseObject object) {
2108: auxiliaryDatabaseObjects.add(object);
2109: }
2110:
2111: public Map getSqlFunctions() {
2112: return sqlFunctions;
2113: }
2114:
2115: public void addSqlFunction(String functionName, SQLFunction function) {
2116: sqlFunctions.put(functionName, function);
2117: }
2118: }
|