HHH-5375 - Merge AnnotationConfiguration into Configuration

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@20092 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Steve Ebersole 2010-07-30 20:02:23 +00:00
parent ef46a4efb7
commit 3ecbfeb2b2
24 changed files with 2450 additions and 2042 deletions

View File

@ -29,6 +29,12 @@
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<exclusions>
<exclusion>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
@ -43,6 +49,33 @@
<artifactId>validation-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2</version>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>stax-api</artifactId>
<groupId>javax.xml.stream</groupId>
</exclusion>
<exclusion>
<artifactId>activation</artifactId>
<groupId>javax.activation</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.1.12</version>
<scope>test</scope>
</dependency>
<!-- optional deps for bytecode providers until those are finally properly scoped -->
<dependency>

File diff suppressed because it is too large Load Diff

View File

@ -21,29 +21,8 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
// $Id$
package org.hibernate.cfg;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.hibernate.AnnotationException;
import org.hibernate.MappingException;
import org.hibernate.annotations.AnyMetaDef;
import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.engine.NamedQueryDefinition;
import org.hibernate.engine.NamedSQLQueryDefinition;
import org.hibernate.engine.ResultSetMappingDefinition;
import org.hibernate.mapping.FetchProfile;
import org.hibernate.mapping.IdGenerator;
import org.hibernate.mapping.Join;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Table;
/**
* Allow annotation related mappings
* <p/>
@ -51,161 +30,9 @@ import org.hibernate.mapping.Table;
*
* @author Emmanuel Bernard
* @author Hardy Ferentschik
*
* @deprecated All functionality has been moved up to {@link Mappings}
*/
@Deprecated
public interface ExtendedMappings extends Mappings {
/**
* Adds a default id generator.
*
* @param generator The id generator
*/
public void addDefaultGenerator(IdGenerator generator);
/**
* Retrieve the id-generator by name.
*
* @param name The generator name.
*
* @return The generator, or null.
*/
public IdGenerator getGenerator(String name);
/**
* Try to find the generator from the localGenerators
* and then from the global generator list
*
* @param name generator name
* @param localGenerators local generators
*
* @return the appropriate idgenerator or null if not found
*/
public IdGenerator getGenerator(String name, Map<String, IdGenerator> localGenerators);
/**
* Add a generator.
*
* @param generator The generator to add.
*/
public void addGenerator(IdGenerator generator);
/**
* Add a generator table properties.
*
* @param name The generator name
* @param params The generator table properties.
*/
public void addGeneratorTable(String name, Properties params);
/**
* Retrieve the properties related to a generator table.
*
* @param name generator name
* @param localGeneratorTables local generator tables
*
* @return The properties, or null.
*/
public Properties getGeneratorTableProperties(String name, Map<String, Properties> localGeneratorTables);
/**
* Retrieve join metadata for a particular persistent entity.
*
* @param entityName The entity name
*
* @return The join metadata
*/
public Map<String, Join> getJoins(String entityName);
/**
* Add join metadata for a persistent entity.
*
* @param persistentClass The persistent entity metadata.
* @param joins The join metadata to add.
*
* @throws MappingException
*/
public void addJoins(PersistentClass persistentClass, Map<String, Join> joins);
/**
* Get and maintain a cache of class type.
*
* @param clazz The XClass mapping
*
* @return The class type.
*/
public AnnotatedClassType getClassType(XClass clazz);
/**
* FIXME should be private but will this break things?
* Add a class type.
*
* @param clazz The XClass mapping.
*
* @return The class type.
*/
public AnnotatedClassType addClassType(XClass clazz);
/**
* @deprecated Use {@link #getUniqueConstraintHoldersByTable} instead
*/
@SuppressWarnings({ "JavaDoc" })
public Map<Table, List<String[]>> getTableUniqueConstraints();
public Map<Table, List<UniqueConstraintHolder>> getUniqueConstraintHoldersByTable();
/**
* @deprecated Use {@link #addUniqueConstraintHolders} instead
*/
@SuppressWarnings({ "JavaDoc" })
public void addUniqueConstraints(Table table, List uniqueConstraints);
public void addUniqueConstraintHolders(Table table, List<UniqueConstraintHolder> uniqueConstraintHolders);
public void addMappedBy(String entityName, String propertyName, String inversePropertyName);
public String getFromMappedBy(String entityName, String propertyName);
public void addPropertyReferencedAssociation(String entityName, String propertyName, String propertyRef);
public String getPropertyReferencedAssociation(String entityName, String propertyName);
public ReflectionManager getReflectionManager();
public void addDefaultQuery(String name, NamedQueryDefinition query);
public void addDefaultSQLQuery(String name, NamedSQLQueryDefinition query);
public void addDefaultResultSetMapping(ResultSetMappingDefinition definition);
public Map getClasses();
public void addAnyMetaDef(AnyMetaDef defAnn) throws AnnotationException;
public AnyMetaDef getAnyMetaDef(String name);
public boolean isInSecondPass();
/**
* Return the property annotated with @MapsId("propertyName") if any.
* Null otherwise
*/
public PropertyData getPropertyAnnotatedWithMapsId(XClass entityType, String propertyName);
public void addPropertyAnnotatedWithMapsId(XClass entityType, PropertyData property);
/**
* Should we use the new generator strategy mappings. This is controlled by the
* {@link AnnotationConfiguration#USE_NEW_ID_GENERATOR_MAPPINGS} setting.
*
* @return True if the new generators should be used, false otherwise.
*/
public boolean useNewGeneratorMappings();
/**
* Return the property annotated with @ToOne and @Id if any.
* Null otherwise
*/
public PropertyData getPropertyAnnotatedWithIdAndToOne(XClass entityType, String propertyName);
void addToOneAndIdProperty(XClass entity, PropertyData property);
}

View File

@ -23,7 +23,9 @@
*/
package org.hibernate.cfg;
import org.dom4j.Document;
import java.util.Set;
import org.hibernate.util.XMLHelper;
/**
* Represents a mapping queued for delayed processing to await
@ -34,12 +36,14 @@ import org.dom4j.Document;
public class ExtendsQueueEntry {
private final String explicitName;
private final String mappingPackage;
private final Document document;
private final XMLHelper.MetadataXml metadataXml;
private final Set<String> entityNames;
public ExtendsQueueEntry(String explicitName, String mappingPackage, Document document) {
public ExtendsQueueEntry(String explicitName, String mappingPackage, XMLHelper.MetadataXml metadataXml, Set<String> entityNames) {
this.explicitName = explicitName;
this.mappingPackage = mappingPackage;
this.document = document;
this.metadataXml = metadataXml;
this.entityNames = entityNames;
}
public String getExplicitName() {
@ -50,7 +54,11 @@ public class ExtendsQueueEntry {
return mappingPackage;
}
public Document getDocument() {
return document;
public XMLHelper.MetadataXml getMetadataXml() {
return metadataXml;
}
public Set<String> getEntityNames() {
return entityNames;
}
}

View File

@ -97,6 +97,8 @@ import org.hibernate.type.TypeFactory;
import org.hibernate.util.JoinedIterator;
import org.hibernate.util.ReflectHelper;
import org.hibernate.util.StringHelper;
import org.hibernate.util.XMLHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -120,37 +122,38 @@ public final class HbmBinder {
* The main contract into the hbm.xml-based binder. Performs necessary binding operations
* represented by the given DOM.
*
* @param doc The DOM to be parsed and bound.
* @param metadataXml The DOM to be parsed and bound.
* @param mappings Current bind state.
* @param inheritedMetas Any inherited meta-tag information.
* @param entityNames Any state
*
* @throws MappingException
*/
public static void bindRoot(Document doc, Mappings mappings, java.util.Map inheritedMetas)
throws MappingException {
public static void bindRoot(
XMLHelper.MetadataXml metadataXml,
Mappings mappings,
java.util.Map inheritedMetas,
java.util.Set<String> entityNames) throws MappingException {
java.util.List names = HbmBinder.getExtendsNeeded( doc, mappings );
final Document doc = metadataXml.getXmlDocument();
final Element hibernateMappingElement = doc.getRootElement();
java.util.List<String> names = HbmBinder.getExtendsNeeded( metadataXml, mappings );
if ( !names.isEmpty() ) {
// classes mentioned in extends not available - so put it in queue
Element hmNode = doc.getRootElement();
Attribute packNode = hmNode.attribute( "package" );
String packageName = null;
if ( packNode != null ) {
packageName = packNode.getValue();
}
Iterator itr = names.iterator();
while ( itr.hasNext() ) {
String extendsName = (String) itr.next();
mappings.addToExtendsQueue( new ExtendsQueueEntry( extendsName, packageName, doc ) );
Attribute packageAttribute = hibernateMappingElement.attribute( "package" );
String packageName = packageAttribute == null ? null : packageAttribute.getValue();
for ( String name : names ) {
mappings.addToExtendsQueue( new ExtendsQueueEntry( name, packageName, metadataXml, entityNames ) );
}
return;
}
Element hmNode = doc.getRootElement();
// get meta's from <hibernate-mapping>
inheritedMetas = getMetas( hmNode, inheritedMetas, true );
extractRootAttributes( hmNode, mappings );
inheritedMetas = getMetas( hibernateMappingElement, inheritedMetas, true );
extractRootAttributes( hibernateMappingElement, mappings );
Iterator rootChildren = hmNode.elementIterator();
Iterator rootChildren = hibernateMappingElement.elementIterator();
while ( rootChildren.hasNext() ) {
final Element element = (Element) rootChildren.next();
final String elementName = element.getName();
@ -1465,6 +1468,9 @@ public final class HbmBinder {
null,
path
);
if ( ownerTable.isQuoted() ) {
tableName = StringHelper.quote( tableName );
}
}
Attribute schemaNode = node.attribute( "schema" );
String schema = schemaNode == null ?
@ -3066,14 +3072,14 @@ public final class HbmBinder {
* For the given document, locate all extends attributes which refer to
* entities (entity-name or class-name) not defined within said document.
*
* @param doc The document to check
* @param metadataXml The document to check
* @param mappings The already processed mappings.
* @return The list of unresolved extends names.
*/
public static java.util.List getExtendsNeeded(Document doc, Mappings mappings) {
java.util.List extendz = new ArrayList();
public static java.util.List<String> getExtendsNeeded(XMLHelper.MetadataXml metadataXml, Mappings mappings) {
java.util.List<String> extendz = new ArrayList<String>();
Iterator[] subclasses = new Iterator[3];
final Element hmNode = doc.getRootElement();
final Element hmNode = metadataXml.getXmlDocument().getRootElement();
Attribute packNode = hmNode.attribute( "package" );
final String packageName = packNode == null ? null : packNode.getValue();
@ -3107,7 +3113,7 @@ public final class HbmBinder {
// extends names which require us to delay processing (i.e.
// external to this document and not yet processed) are contained
// in the returned result
final java.util.Set set = new HashSet( extendz );
final java.util.Set<String> set = new HashSet<String>( extendz );
EntityElementHandler handler = new EntityElementHandler() {
public void handleEntity(String entityName, String className, Mappings mappings) {
if ( entityName != null ) {

View File

@ -25,18 +25,25 @@ package org.hibernate.cfg;
import java.io.Serializable;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Map;
import java.util.ListIterator;
import org.hibernate.AnnotationException;
import org.hibernate.DuplicateMappingException;
import org.hibernate.MappingException;
import org.hibernate.annotations.AnyMetaDef;
import org.hibernate.annotations.common.reflection.ReflectionManager;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.id.factory.DefaultIdentifierGeneratorFactory;
import org.hibernate.engine.FilterDefinition;
import org.hibernate.engine.NamedQueryDefinition;
import org.hibernate.engine.NamedSQLQueryDefinition;
import org.hibernate.engine.ResultSetMappingDefinition;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.IdGenerator;
import org.hibernate.mapping.Join;
import org.hibernate.mapping.MetadataSource;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Table;
@ -187,7 +194,7 @@ public interface Mappings {
*
* @return Iterator over class metadata.
*/
public Iterator iterateClasses();
public Iterator<PersistentClass> iterateClasses();
/**
* Retrieves the entity mapping metadata for the given entity name.
@ -238,7 +245,7 @@ public interface Mappings {
*
* @return Iterator over collection metadata.
*/
public Iterator iterateCollections();
public Iterator<Collection> iterateCollections();
/**
* Add collection mapping metadata to this repository.
@ -264,16 +271,16 @@ public interface Mappings {
*
* @return Iterator over table metadata.
*/
public Iterator iterateTables();
public Iterator<Table> iterateTables();
/**
* Adds table metedata to this repository returning the created
* Adds table metadata to this repository returning the created
* metadata instance.
*
* @param schema The named schema in which the table belongs (or null).
* @param catalog The named catalog in which the table belongs (or null).
* @param name The table name
* @param subselect A select statement wwich defines a logical table, much
* @param subselect A select statement which defines a logical table, much
* like a DB view.
* @param isAbstract Is the table abstract (i.e. not really existing in the DB)?
* @return The created table metadata, or the existing reference.
@ -287,7 +294,7 @@ public interface Mappings {
* @param catalog The named catalog in which the table belongs (or null).
* @param name The table name
* @param isAbstract Is the table abstract (i.e. not really existing in the DB)?
* @param subselect A select statement wwich defines a logical table, much
* @param subselect A select statement which defines a logical table, much
* like a DB view.
* @param includedTable ???
* @return The created table metadata.
@ -374,7 +381,7 @@ public interface Mappings {
/**
* Retrieves a filter definition by name.
*
* @param name The name of the filter defintion to retrieve.
* @param name The name of the filter definition to retrieve.
* @return The filter definition, or null.
*/
public FilterDefinition getFilterDefinition(String name);
@ -397,21 +404,35 @@ public interface Mappings {
public FetchProfile findOrCreateFetchProfile(String name, MetadataSource source);
/**
* Retrieves an iterator over the metadata pertaining to all auxilary database objects int this repository.
*
* @return Iterator over the auxilary database object metadata.
* @deprecated To fix misspelling; use {@link #iterateAuxiliaryDatabaseObjects} instead
*/
public Iterator iterateAuxliaryDatabaseObjects();
@Deprecated
@SuppressWarnings({ "JavaDoc" })
public Iterator<AuxiliaryDatabaseObject> iterateAuxliaryDatabaseObjects();
/**
* Same as {@link #iterateAuxliaryDatabaseObjects()} except that here the iterator is reversed.
* Retrieves an iterator over the metadata pertaining to all auxiliary database objects int this repository.
*
* @return Iterator over the auxiliary database object metadata.
*/
public Iterator<AuxiliaryDatabaseObject> iterateAuxiliaryDatabaseObjects();
/**
* @deprecated To fix misspelling; use {@link #iterateAuxiliaryDatabaseObjectsInReverse} instead
*/
@Deprecated
@SuppressWarnings({ "JavaDoc" })
public ListIterator<AuxiliaryDatabaseObject> iterateAuxliaryDatabaseObjectsInReverse();
/**
* Same as {@link #iterateAuxiliaryDatabaseObjects()} except that here the iterator is reversed.
*
* @return The reversed iterator.
*/
public ListIterator iterateAuxliaryDatabaseObjectsInReverse();
public ListIterator<AuxiliaryDatabaseObject> iterateAuxiliaryDatabaseObjectsInReverse();
/**
* Add metadata pertaining to an auxilary database object to this repository.
* Add metadata pertaining to an auxiliary database object to this repository.
*
* @param auxiliaryDatabaseObject The metadata.
*/
@ -565,4 +586,169 @@ public interface Mappings {
* @return The configuration properties
*/
public Properties getConfigurationProperties();
/**
* Adds a default id generator.
*
* @param generator The id generator
*/
public void addDefaultGenerator(IdGenerator generator);
/**
* Retrieve the id-generator by name.
*
* @param name The generator name.
*
* @return The generator, or null.
*/
public IdGenerator getGenerator(String name);
/**
* Try to find the generator from the localGenerators
* and then from the global generator list
*
* @param name generator name
* @param localGenerators local generators
*
* @return the appropriate idgenerator or null if not found
*/
public IdGenerator getGenerator(String name, Map<String, IdGenerator> localGenerators);
/**
* Add a generator.
*
* @param generator The generator to add.
*/
public void addGenerator(IdGenerator generator);
/**
* Add a generator table properties.
*
* @param name The generator name
* @param params The generator table properties.
*/
public void addGeneratorTable(String name, Properties params);
/**
* Retrieve the properties related to a generator table.
*
* @param name generator name
* @param localGeneratorTables local generator tables
*
* @return The properties, or null.
*/
public Properties getGeneratorTableProperties(String name, Map<String, Properties> localGeneratorTables);
/**
* Retrieve join metadata for a particular persistent entity.
*
* @param entityName The entity name
*
* @return The join metadata
*/
public Map<String, Join> getJoins(String entityName);
/**
* Add join metadata for a persistent entity.
*
* @param persistentClass The persistent entity metadata.
* @param joins The join metadata to add.
*
* @throws MappingException
*/
public void addJoins(PersistentClass persistentClass, Map<String, Join> joins);
/**
* Get and maintain a cache of class type.
*
* @param clazz The XClass mapping
*
* @return The class type.
*/
public AnnotatedClassType getClassType(XClass clazz);
/**
* FIXME should be private but will this break things?
* Add a class type.
*
* @param clazz The XClass mapping.
*
* @return The class type.
*/
public AnnotatedClassType addClassType(XClass clazz);
/**
* @deprecated Use {@link #getUniqueConstraintHoldersByTable} instead
*/
@SuppressWarnings({ "JavaDoc" })
public Map<Table, List<String[]>> getTableUniqueConstraints();
public Map<Table, List<UniqueConstraintHolder>> getUniqueConstraintHoldersByTable();
/**
* @deprecated Use {@link #addUniqueConstraintHolders} instead
*/
@SuppressWarnings({ "JavaDoc" })
public void addUniqueConstraints(Table table, List uniqueConstraints);
public void addUniqueConstraintHolders(Table table, List<UniqueConstraintHolder> uniqueConstraintHolders);
public void addMappedBy(String entityName, String propertyName, String inversePropertyName);
public String getFromMappedBy(String entityName, String propertyName);
public void addPropertyReferencedAssociation(String entityName, String propertyName, String propertyRef);
public String getPropertyReferencedAssociation(String entityName, String propertyName);
public ReflectionManager getReflectionManager();
public void addDefaultQuery(String name, NamedQueryDefinition query);
public void addDefaultSQLQuery(String name, NamedSQLQueryDefinition query);
public void addDefaultResultSetMapping(ResultSetMappingDefinition definition);
public Map getClasses();
public void addAnyMetaDef(AnyMetaDef defAnn) throws AnnotationException;
public AnyMetaDef getAnyMetaDef(String name);
public boolean isInSecondPass();
/**
* Return the property annotated with @MapsId("propertyName") if any.
* Null otherwise
*/
public PropertyData getPropertyAnnotatedWithMapsId(XClass entityType, String propertyName);
public void addPropertyAnnotatedWithMapsId(XClass entityType, PropertyData property);
/**
* Should we use the new generator strategy mappings. This is controlled by the
* {@link Configuration#USE_NEW_ID_GENERATOR_MAPPINGS} setting.
*
* @return True if the new generators should be used, false otherwise.
*/
public boolean useNewGeneratorMappings();
/**
* Return the property annotated with @ToOne and @Id if any.
* Null otherwise
*/
public PropertyData getPropertyAnnotatedWithIdAndToOne(XClass entityType, String propertyName);
void addToOneAndIdProperty(XClass entity, PropertyData property);
}

View File

@ -21,30 +21,47 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
// $Id$
package org.hibernate.cfg;
import org.hibernate.HibernateException;
/**
* Enumeration of the types of sources of mapping metadata
*
* @author Hardy Ferentschik
* @author Steve Ebersole
*/
public enum ConfigurationArtefactType {
HBM,
CLASS;
public enum MetadataSourceType {
/**
* Indicates metadata coming from <tt>hbm.xml</tt> files
*/
HBM( "hbm" ),
/**
* Indicates metadata coming from either annotations, <tt>orx.xml</tt> or a combination of the two.
*/
CLASS( "class" );
static ConfigurationArtefactType parsePrecedence(String s) {
if ( s.equalsIgnoreCase( "hbm" ) ) {
private final String name;
private MetadataSourceType(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
static MetadataSourceType parsePrecedence(String value) {
if ( HBM.name.equalsIgnoreCase( value ) ) {
return HBM;
}
else if ( s.equalsIgnoreCase( "class" ) ) {
if ( CLASS.name.equalsIgnoreCase( value ) ) {
return CLASS;
}
else {
throw new HibernateException( "'" + s + "' - invalid value for precedence configuration." );
}
throw new HibernateException( "Unknown metadata source type value [" + value + "]" );
}
}

View File

@ -23,6 +23,9 @@
*/
package org.hibernate.cfg.annotations.reflection;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.lang.reflect.AnnotatedElement;
import java.util.ArrayList;
import java.util.HashMap;
@ -47,11 +50,19 @@ import org.hibernate.util.ReflectHelper;
*
* @author Emmanuel Bernard
*/
public class JPAMetadataProvider implements MetadataProvider {
private MetadataProvider delegate = new JavaMetadataProvider();
public class JPAMetadataProvider implements MetadataProvider, Serializable {
private transient MetadataProvider delegate = new JavaMetadataProvider();
private transient Map<Object, Object> defaults;
private transient Map<AnnotatedElement, AnnotationReader> cache = new HashMap<AnnotatedElement, AnnotationReader>(100);
//all of the above can be safely rebuilt from XMLContext: only XMLContext this object is serialized
private XMLContext xmlContext = new XMLContext();
private Map<Object, Object> defaults;
private Map<AnnotatedElement, AnnotationReader> cache = new HashMap<AnnotatedElement, AnnotationReader>(100);
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
ois.defaultReadObject();
delegate = new JavaMetadataProvider();
cache = new HashMap<AnnotatedElement, AnnotationReader>(100);
}
public AnnotationReader getAnnotationReader(AnnotatedElement annotatedElement) {
AnnotationReader reader = cache.get( annotatedElement );

View File

@ -26,6 +26,7 @@
package org.hibernate.cfg.annotations.reflection;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -45,7 +46,7 @@ import org.slf4j.Logger;
/**
* @author Emmanuel Bernard
*/
public class XMLContext {
public class XMLContext implements Serializable {
private Logger log = LoggerFactory.getLogger( XMLContext.class );
private Default globalDefaults;
private Map<String, Element> classOverriding = new HashMap<String, Element>();
@ -224,7 +225,7 @@ public class XMLContext {
return hasContext;
}
public static class Default {
public static class Default implements Serializable {
private AccessType access;
private String packageName;
private String schema;

View File

@ -1,10 +1,10 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Middleware LLC.
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
@ -20,28 +20,47 @@
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*
*/
package org.hibernate.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.io.StringReader;
import java.net.URL;
import java.util.List;
import javax.xml.XMLConstants;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.dom4j.Document;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.io.DOMReader;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.dom4j.io.DOMReader;
import org.dom4j.io.SAXReader;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.dom4j.Element;
import org.dom4j.DocumentFactory;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.hibernate.HibernateException;
import org.hibernate.InvalidMappingException;
/**
* Small helper class that lazy loads DOM and SAX reader and keep them for fast use afterwards.
*/
public final class XMLHelper {
public static final String ORM_1_SCHEMA_NAME = "org/hibernate/ejb/orm_1_0.xsd";
public static final String ORM_2_SCHEMA_NAME = "org/hibernate/ejb/orm_2_0.xsd";
private static final Logger log = LoggerFactory.getLogger(XMLHelper.class);
public static final EntityResolver DEFAULT_DTD_RESOLVER = new DTDEntityResolver();
@ -54,11 +73,18 @@ public final class XMLHelper {
* to errorList
*/
public SAXReader createSAXReader(String file, List errorsList, EntityResolver entityResolver) {
if (saxReader==null) saxReader = new SAXReader();
SAXReader saxReader = resolveSAXReader();
saxReader.setEntityResolver(entityResolver);
saxReader.setErrorHandler( new ErrorLogger(file, errorsList) );
saxReader.setMergeAdjacentText(true);
saxReader.setValidation(true);
return saxReader;
}
private SAXReader resolveSAXReader() {
if ( saxReader == null ) {
saxReader = new SAXReader();
saxReader.setMergeAdjacentText(true);
saxReader.setValidation(true);
}
return saxReader;
}
@ -72,8 +98,9 @@ public final class XMLHelper {
public static class ErrorLogger implements ErrorHandler {
private String file;
private List errors;
ErrorLogger(String file, List errors) {
private List<SAXParseException> errors;
private ErrorLogger(String file, List errors) {
this.file=file;
this.errors = errors;
}
@ -108,4 +135,249 @@ public final class XMLHelper {
}
}
public static interface MetadataXmlSource {
public static interface Origin {
public String getType();
public String getName();
}
public Origin getOrigin();
public InputSource getInputSource();
}
public static interface MetadataXml extends Serializable {
public boolean isOrmXml();
public Document getXmlDocument();
public String getOriginType();
public String getOriginName();
}
private static class MetadataXmlImpl implements MetadataXml, Serializable {
private final Document xmlDocument;
private final boolean isOrmXml;
private final String originType;
private final String originName;
private MetadataXmlImpl(Document xmlDocument, String originType, String originName) {
this.xmlDocument = xmlDocument;
this.originType = originType;
this.originName = originName;
this.isOrmXml = "entity-mappings".equals( xmlDocument.getRootElement().getName() );
}
public Document getXmlDocument() {
return xmlDocument;
}
public boolean isOrmXml() {
return isOrmXml;
}
public String getOriginType() {
return originType;
}
public String getOriginName() {
return originName;
}
}
public MetadataXml buildMetadataXml(Document xmlDocument, String originType, String originName) {
return new MetadataXmlImpl( xmlDocument, originType, originName );
}
public MetadataXml readMappingDocument(EntityResolver entityResolver, MetadataXmlSource source) {
// IMPL NOTE : this is the legacy logic as pulled from the old AnnotationConfiguration code
Exception failure;
ErrorLogger2 errorHandler = new ErrorLogger2();
SAXReader saxReader = new SAXReader();
saxReader.setEntityResolver( entityResolver );
saxReader.setErrorHandler( errorHandler );
saxReader.setMergeAdjacentText( true );
saxReader.setValidation( true );
Document document = null;
try {
// first try with orm 2.0 xsd validation
setValidationFor( saxReader, "orm_2_0.xsd" );
document = saxReader.read( source.getInputSource() );
if ( errorHandler.error != null ) {
throw errorHandler.error;
}
return buildMetadataXml( document, source.getOrigin().getType(), source.getOrigin().getName() );
}
catch ( Exception orm2Problem ) {
log.debug( "Problem parsing XML using orm 2 xsd : {}", orm2Problem.getMessage() );
failure = orm2Problem;
errorHandler.error = null;
if ( document != null ) {
// next try with orm 1.0 xsd validation
try {
setValidationFor( saxReader, "orm_1_0.xsd" );
document = saxReader.read( new StringReader( document.asXML() ) );
if ( errorHandler.error != null ) {
throw errorHandler.error;
}
return buildMetadataXml( document, source.getOrigin().getType(), source.getOrigin().getName() );
}
catch ( Exception orm1Problem ) {
log.debug( "Problem parsing XML using orm 1 xsd : {}", orm1Problem.getMessage() );
errorHandler.error = null;
}
}
}
throw new InvalidMappingException( "Unable to read XML", source.getOrigin().getType(), source.getOrigin().getName(), failure );
}
private void setValidationFor(SAXReader saxReader, String xsd) {
try {
saxReader.setFeature( "http://apache.org/xml/features/validation/schema", true );
//saxReader.setFeature( "http://apache.org/xml/features/validation/dynamic", true );
//set the default schema locators
saxReader.setProperty(
"http://apache.org/xml/properties/schema/external-schemaLocation",
"http://java.sun.com/xml/ns/persistence/orm " + xsd
);
}
catch ( SAXException e ) {
saxReader.setValidation( false );
}
}
// public MetadataXml readMappingDocument(EntityResolver entityResolver, MetadataXmlSource source) {
// Exception failure;
// ErrorLogger2 errorHandler = new ErrorLogger2();
//
// SAXReader saxReader = resolveSAXReader();
// saxReader.setEntityResolver( entityResolver );
// saxReader.setErrorHandler( errorHandler );
//
// try {
// Document document = saxReader.read( source.getInputSource() );
// if ( errorHandler.error != null ) {
// Exception problem = errorHandler.error;
// errorHandler.error = null;
// throw problem;
// }
// }
// catch ( Exception parseError ) {
// log.debug( "Problem parsing XML document : {}", parseError.getMessage() );
// }
// // first try with orm 2.0 xsd validation
// try {
// SAXReader saxReader = orm2SaxReader();
// if ( errorHandler.error != null ) {
// Exception problem = errorHandler.error;
// errorHandler.error = null;
// throw problem;
// }
// return buildMetadataXml( document, source.getOrigin().getType(), source.getOrigin().getName() );
// }
// catch ( Exception orm2Problem ) {
// log.debug( "Problem parsing XML using orm 2 xsd : {}", orm2Problem.getMessage() );
// failure = orm2Problem;
//
// // next try with orm 1.0 xsd validation
// try {
// SAXReader saxReader = orm1SaxReader();
// saxReader.setEntityResolver( entityResolver );
// saxReader.setErrorHandler( errorHandler );
// Document document = saxReader.read( source.getInputSource() );
// if ( errorHandler.error != null ) {
// Exception problem = errorHandler.error;
// errorHandler.error = null;
// throw problem;
// }
// return buildMetadataXml( document, source.getOrigin().getType(), source.getOrigin().getName() );
// }
// catch ( Exception orm1Problem ) {
// log.debug( "Problem parsing XML using orm 1 xsd : {}", orm1Problem.getMessage() );
// }
// }
// throw new InvalidMappingException( "Unable to read XML", source.getOrigin().getType(), source.getOrigin().getName(), failure );
// }
private static class ErrorLogger2 implements ErrorHandler {
private SAXParseException error; // capture the initial error
public void error(SAXParseException error) {
log.error( "Error parsing XML (" + error.getLineNumber() + ") : " + error.getMessage() );
if ( this.error == null ) {
this.error = error;
}
}
public void fatalError(SAXParseException error) {
error( error );
}
public void warning(SAXParseException warn) {
log.error( "Warning parsing XML (" + error.getLineNumber() + ") : " + error.getMessage() );
}
}
private static SAXReader orm2SaxReader;
private static SAXReader orm2SaxReader() throws IOException, SAXException {
if ( orm2SaxReader == null ) {
orm2SaxReader = buildReaderWithSchema( orm2Schema() );
}
return orm2SaxReader;
}
private static Schema orm2Schema;
private static Schema orm2Schema() throws IOException, SAXException {
if ( orm2Schema == null ) {
orm2Schema = resolveLocalSchema( ORM_2_SCHEMA_NAME );
}
return orm2Schema;
}
private static Schema resolveLocalSchema(String schemaName) throws IOException, SAXException {
URL url = ConfigHelper.findAsResource( schemaName );
InputStream schemaStream = url.openStream();
try {
StreamSource source = new StreamSource(url.openStream());
SchemaFactory schemaFactory = SchemaFactory.newInstance( XMLConstants.W3C_XML_SCHEMA_NS_URI );
return schemaFactory.newSchema(source);
}
finally {
schemaStream.close();
}
}
private static SAXReader buildReaderWithSchema(Schema schema) throws SAXException {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setSchema( schema );
try {
SAXReader saxReader = new SAXReader( factory.newSAXParser().getXMLReader() );
saxReader.setMergeAdjacentText( true );
saxReader.setValidation( true );
return saxReader;
}
catch ( ParserConfigurationException e ) {
throw new HibernateException( "Unable to build SAXReader with XSD support", e );
}
}
private static SAXReader orm1SaxReader;
private static SAXReader orm1SaxReader() throws IOException, SAXException {
if ( orm1SaxReader == null ) {
orm1SaxReader = buildReaderWithSchema( orm1Schema() );
}
return orm1SaxReader;
}
private static Schema orm1Schema;
private static Schema orm1Schema() throws IOException, SAXException {
if ( orm1Schema == null ) {
orm1Schema = resolveLocalSchema( ORM_1_SCHEMA_NAME );
}
return orm1Schema;
}
}

View File

@ -90,10 +90,6 @@ public class ExecutionEnvironment {
settings.configure( configuration );
applyMappings( configuration );
applyCacheSettings( configuration );
if ( settings.createSchema() ) {
configuration.setProperty( Environment.HBM2DDL_AUTO, "create-drop" );
}
@ -101,7 +97,10 @@ public class ExecutionEnvironment {
// make sure we use the same dialect...
configuration.setProperty( Environment.DIALECT, getDialect().getClass().getName() );
applyMappings( configuration );
configuration.buildMappings();
applyCacheSettings( configuration );
settings.afterConfigurationBuilt( configuration.createMappings(), getDialect() );
SessionFactory sessionFactory = configuration.buildSessionFactory();
@ -113,8 +112,11 @@ public class ExecutionEnvironment {
private void applyMappings(Configuration configuration) {
String[] mappings = settings.getMappings();
for ( int i = 0; i < mappings.length; i++ ) {
configuration.addResource( settings.getBaseForMappings() + mappings[i], ExecutionEnvironment.class.getClassLoader() );
for ( String mapping : mappings ) {
configuration.addResource(
settings.getBaseForMappings() + mapping,
ExecutionEnvironment.class.getClassLoader()
);
}
}

View File

@ -42,6 +42,20 @@
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1</version>
<exclusions>
<exclusion>
<groupId>xml-apis</groupId>
<artifactId>xml-apis</artifactId>
</exclusion>
<exclusion>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
</exclusion>
<exclusion>
<groupId>xom</groupId>
<artifactId>xom</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>

View File

@ -106,17 +106,6 @@ public class ConfigurationTest extends junit.framework.TestCase {
sf.close();
}
public void testDeclarativeAnnWoAnnConfig() throws Exception {
Configuration cfg = new Configuration();
try {
cfg.configure( "org/hibernate/test/annotations/hibernate.cfg.xml" );
fail( "Configuration object should fail when finding annotated elements declarations" );
}
catch (MappingException e) {
//success
}
}
public void testHbmWithSubclassExtends() throws Exception {
AnnotationConfiguration cfg = new AnnotationConfiguration();
cfg.configure( "org/hibernate/test/annotations/hibernate.cfg.xml" );

View File

@ -29,6 +29,8 @@ package org.hibernate.test.cascade.circle;
import junit.framework.Test;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.testing.junit.functional.FunctionalTestCase;
import org.hibernate.testing.junit.functional.FunctionalTestClassTestSuite;
@ -64,8 +66,12 @@ public class CascadeMergeToChildBeforeParentTest extends FunctionalTestCase {
return new String[] {
"cascade/circle/CascadeMergeToChildBeforeParent.hbm.xml"
};
}@Override
public void configure(Configuration cfg) {
super.configure( cfg );
cfg.setProperty( Environment.CHECK_NULLABILITY, "true" );
}
public static Test suite() {
return new FunctionalTestClassTestSuite( CascadeMergeToChildBeforeParentTest.class );
}

View File

@ -67,6 +67,7 @@ public class MultiPathCircleCascadeTest extends FunctionalTestCase {
public void configure(Configuration cfg) {
cfg.setProperty( Environment.GENERATE_STATISTICS, "true");
cfg.setProperty( Environment.STATEMENT_BATCH_SIZE, "0" );
cfg.setProperty( Environment.CHECK_NULLABILITY, "true" );
}
public String[] getMappings() {

View File

@ -21,6 +21,9 @@
*/
package org.hibernate.test.cfg;
import javax.persistence.Entity;
import javax.persistence.Id;
import junit.framework.Test;
import junit.framework.TestSuite;
@ -86,6 +89,7 @@ public class ConfigurationSerializationTest extends UnitTestCase {
"legacy/UpDown.hbm.xml",
"legacy/Vetoer.hbm.xml",
"legacy/WZ.hbm.xml",
"cfg/orm-serializable.xml"
};
public void testConfiguraionSerializability() {
@ -94,6 +98,8 @@ public class ConfigurationSerializationTest extends UnitTestCase {
cfg.addResource( "org/hibernate/test/" + file );
}
cfg.addAnnotatedClass( Serial.class );
byte[] bytes = SerializationHelper.serialize( cfg );
cfg = ( Configuration ) SerializationHelper.deserialize( bytes );
@ -101,4 +107,19 @@ public class ConfigurationSerializationTest extends UnitTestCase {
SessionFactory factory = cfg.buildSessionFactory();
factory.close();
}
@Entity
public static class Serial {
private String id;
private String value;
@Id
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
}

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1.0"
>
<table-generator name="EMP_GEN" table="GENERATOR_TABLE"
pk-column-name="pkey" pk-column-value="EMP"
value-column-name="hi" allocation-size="20"/>
</entity-mappings>

View File

@ -29,6 +29,7 @@ public class ExtendsTest extends UnitTestCase {
Configuration cfg = new Configuration();
cfg.addResource( getBaseForMappings() + "extendshbm/allinone.hbm.xml" );
cfg.buildMappings();
assertNotNull( cfg.getClassMapping( "org.hibernate.test.extendshbm.Customer" ) );
assertNotNull( cfg.getClassMapping( "org.hibernate.test.extendshbm.Person" ) );
assertNotNull( cfg.getClassMapping( "org.hibernate.test.extendshbm.Employee" ) );

View File

@ -9,6 +9,8 @@ import junit.textui.TestRunner;
import org.hibernate.PropertyValueException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.testing.junit.functional.FunctionalTestClassTestSuite;
/**
@ -34,8 +36,10 @@ public class ComponentNotNullTest extends LegacyTestCase {
return new FunctionalTestClassTestSuite( ComponentNotNullTest.class );
}
public static void main(String[] args) throws Exception {
TestRunner.run(suite());
@Override
public void configure(Configuration cfg) {
super.configure( cfg );
cfg.setProperty( Environment.CHECK_NULLABILITY, "true" );
}
public void testComponentNotNull() throws Exception {

View File

@ -3,6 +3,7 @@ package org.hibernate.test.legacy;
import java.util.Iterator;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.DefaultNamingStrategy;
import org.hibernate.cfg.Environment;
import org.hibernate.hql.classic.ClassicQueryTranslatorFactory;
import org.hibernate.testing.junit.functional.FunctionalTestCase;
@ -53,6 +54,7 @@ public abstract class LegacyTestCase extends FunctionalTestCase {
subs += ", true=1, false=0";
}
cfg.getProperties().setProperty( Environment.QUERY_SUBSTITUTIONS, subs );
cfg.setNamingStrategy( DefaultNamingStrategy.INSTANCE );
}
catch( NumberFormatException nfe ) {
// the Integer#parseInt call failed...

View File

@ -8,6 +8,7 @@ import junit.framework.Test;
import junit.framework.TestSuite;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.Environment;
import org.hibernate.mapping.Bag;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.Component;
@ -36,7 +37,8 @@ public class NonReflectiveBinderTest extends UnitTestCase {
protected void setUp() throws Exception {
super.setUp();
cfg = new Configuration()
.addResource( "org/hibernate/test/legacy/Wicked.hbm.xml" );
.addResource( "org/hibernate/test/legacy/Wicked.hbm.xml" )
.setProperty( "javax.persistence.validation.mode", "none" );
cfg.buildMappings();
}

View File

@ -126,8 +126,10 @@ public class MappingExceptionTest extends UnitTestCase {
String resourceName = "org/hibernate/test/mappingexception/User.hbm.xml";
Configuration cfg = new Configuration();
cfg.addResource( resourceName );
cfg.buildMappings();
try {
cfg.addResource( resourceName );
cfg.buildMappings();
fail();
}
catch ( InvalidMappingException inv ) {

View File

@ -59,6 +59,8 @@ public class CMTTest extends FunctionalTestCase {
public void testConcurrent() throws Exception {
getSessions().getStatistics().clear();
assertNotNull( sfi().getEntityPersister( "Item" ).getCacheAccessStrategy() );
assertEquals( 0, getSessions().getStatistics().getEntityLoadCount() );
SimpleJtaTransactionManagerImpl.getInstance().begin();
Session s = openSession();
@ -111,11 +113,11 @@ public class CMTTest extends FunctionalTestCase {
s2.createCriteria( "Item" ).list();
SimpleJtaTransactionManagerImpl.getInstance().commit();
assertEquals( getSessions().getStatistics().getEntityLoadCount(), 7 );
assertEquals( getSessions().getStatistics().getEntityFetchCount(), 0 );
assertEquals( getSessions().getStatistics().getQueryExecutionCount(), 3 );
assertEquals( getSessions().getStatistics().getQueryCacheHitCount(), 0 );
assertEquals( getSessions().getStatistics().getQueryCacheMissCount(), 0 );
assertEquals( 7, getSessions().getStatistics().getEntityLoadCount() );
assertEquals( 0, getSessions().getStatistics().getEntityFetchCount() );
assertEquals( 3, getSessions().getStatistics().getQueryExecutionCount() );
assertEquals( 0, getSessions().getStatistics().getQueryCacheHitCount() );
assertEquals( 0, getSessions().getStatistics().getQueryCacheMissCount() );
SimpleJtaTransactionManagerImpl.getInstance().begin();
s = openSession();