HHH-14563 Remove DOM4J-based XML mapping

Use JAXB-based XML mapping everywhere.
This commit is contained in:
Yoann Rodière 2021-04-16 13:55:00 +02:00
parent 194e53a0fb
commit 6f5f6b32c3
21 changed files with 25 additions and 3925 deletions

View File

@ -30,7 +30,6 @@ import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.ClassLoaderAccess;
import org.hibernate.boot.spi.MetadataBuildingOptions;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.annotations.reflection.JPAMetadataProvider;
import org.hibernate.cfg.annotations.reflection.internal.JPAXMLOverriddenMetadataProvider;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.engine.config.spi.ConfigurationService;
@ -310,13 +309,7 @@ public class BootstrapContextImpl implements BootstrapContext {
private JavaReflectionManager generateHcannReflectionManager() {
final JavaReflectionManager reflectionManager = new JavaReflectionManager();
if ( metadataBuildingOptions.getXmlMappingOptions().isPreferJaxb() ) {
reflectionManager.setMetadataProvider( new JPAXMLOverriddenMetadataProvider( this ) );
}
else {
// Legacy implementation based on DOM4J, for backwards compatibility.
reflectionManager.setMetadataProvider( new JPAMetadataProvider( this ) );
}
reflectionManager.setMetadataProvider( new JPAXMLOverriddenMetadataProvider( this ) );
return reflectionManager;
}

View File

@ -10,11 +10,8 @@ import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import org.hibernate.boot.MappingException;
import org.hibernate.boot.UnsupportedOrmXsdVersionException;
import org.hibernate.boot.jaxb.Origin;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmHibernateMapping;
@ -29,10 +26,6 @@ import org.hibernate.internal.util.config.ConfigurationException;
import org.jboss.logging.Logger;
import org.dom4j.Document;
import org.dom4j.Node;
import org.dom4j.io.STAXEventReader;
/**
* @author Steve Ebersole
*/
@ -41,14 +34,11 @@ public class MappingBinder extends AbstractBinder {
private final XMLEventFactory xmlEventFactory = XMLEventFactory.newInstance();
private final XmlMappingOptions options;
private JAXBContext hbmJaxbContext;
private JAXBContext entityMappingsJaxbContext;
public MappingBinder(ClassLoaderService classLoaderService, boolean validateXml, XmlMappingOptions options) {
public MappingBinder(ClassLoaderService classLoaderService, boolean validateXml) {
super( classLoaderService, validateXml );
this.options = options;
}
@Override
@ -66,19 +56,11 @@ public class MappingBinder extends AbstractBinder {
}
else {
try {
if ( options.isPreferJaxb() ) {
log.debugf( "Performing JAXB binding of orm.xml document : %s", origin.toString() );
log.debugf( "Performing JAXB binding of orm.xml document : %s", origin.toString() );
XMLEventReader reader = new JpaOrmXmlEventReader( staxEventReader, xmlEventFactory );
JaxbEntityMappings bindingRoot = jaxb( reader, MappingXsdSupport.INSTANCE.latestJpaDescriptor().getSchema(), entityMappingsJaxbContext(), origin );
return new Binding<>( bindingRoot, origin );
}
else {
log.debugf( "Performing DOM4J binding of orm.xml document : %s", origin.toString() );
final XMLEventReader reader = new JpaOrmXmlEventReader( staxEventReader, xmlEventFactory );
return new Binding<>( toDom4jDocument( reader, origin ), origin );
}
XMLEventReader reader = new JpaOrmXmlEventReader( staxEventReader, xmlEventFactory );
JaxbEntityMappings bindingRoot = jaxb( reader, MappingXsdSupport.INSTANCE.latestJpaDescriptor().getSchema(), entityMappingsJaxbContext(), origin );
return new Binding<>( bindingRoot, origin );
}
catch (JpaOrmXmlEventReader.BadVersionException e) {
throw new UnsupportedOrmXsdVersionException( e.getRequestedVersion(), origin );
@ -109,32 +91,4 @@ public class MappingBinder extends AbstractBinder {
}
return entityMappingsJaxbContext;
}
private Document toDom4jDocument(XMLEventReader jpaOrmXmlEventReader, Origin origin) {
// todo : do we need to build a DocumentFactory instance for use here?
// historically we did that to set TCCL since, iirc, dom4j uses TCCL
org.dom4j.io.STAXEventReader staxToDom4jReader = new STAXEventReader() {
@Override
public Node readNode(XMLEventReader reader) throws XMLStreamException {
// dom4j's reader misses handling of XML comments. So if the document we
// are trying to read has comments this process will blow up. So we
// override that to add that support as best we can
XMLEvent event = reader.peek();
if ( javax.xml.stream.events.Comment.class.isInstance( event ) ) {
return super.readComment( reader );
}
return super.readNode( reader );
}
};
try {
return staxToDom4jReader.readDocument( jpaOrmXmlEventReader );
}
catch (XMLStreamException e) {
throw new MappingException(
"An error occurred transforming orm.xml document from StAX to dom4j representation ",
e,
origin
);
}
}
}

View File

@ -72,15 +72,4 @@ public interface XmlMappingOptions {
return true;
}
/**
* Whether to prefer JAXB implementations for XML parsing,
* or to rely on legacy behavior (JAXB for hbm.xml, DOM4J for orm.xml and Envers).
* <p>
* This option will be removed in a future major version (probably ORM 6.0)
* where JAXB will always be used.
*/
default boolean isPreferJaxb() {
return false;
}
}

View File

@ -294,7 +294,7 @@ public class MetadataBuildingProcess {
final EntityHierarchyBuilder hierarchyBuilder = new EntityHierarchyBuilder();
// final MappingBinder mappingBinder = new MappingBinder( true );
// We need to disable validation here. It seems Envers is not producing valid (according to schema) XML
final MappingBinder mappingBinder = new MappingBinder( classLoaderService, false, xmlMappingOptions );
final MappingBinder mappingBinder = new MappingBinder( classLoaderService, false );
for ( AdditionalJaxbMappingProducer producer : producers ) {
log.tracef( "Calling AdditionalJaxbMappingProducer : %s", producer );
Collection<MappingDocument> additionalMappings = producer.produceAdditionalMappings(

View File

@ -35,7 +35,6 @@ import org.hibernate.boot.spi.MetadataBuildingOptions;
import org.hibernate.cfg.AnnotationBinder;
import org.hibernate.cfg.InheritanceState;
import org.hibernate.cfg.annotations.reflection.AttributeConverterDefinitionCollector;
import org.hibernate.cfg.annotations.reflection.JPAMetadataProvider;
import org.hibernate.cfg.annotations.reflection.internal.JPAXMLOverriddenMetadataProvider;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
@ -43,8 +42,6 @@ import org.hibernate.internal.util.collections.CollectionHelper;
import org.jboss.jandex.IndexView;
import org.jboss.logging.Logger;
import org.dom4j.Document;
/**
* @author Steve Ebersole
*/
@ -84,39 +81,21 @@ public class AnnotationMetadataSourceProcessorImpl implements MetadataSourceProc
if ( xmlMappingOptions.isEnabled() ) {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Ewww. This is temporary until we migrate to Jandex + StAX for annotation binding
if ( xmlMappingOptions.isPreferJaxb() ) {
final JPAXMLOverriddenMetadataProvider jpaMetadataProvider = (JPAXMLOverriddenMetadataProvider) ( (MetadataProviderInjector) reflectionManager )
.getMetadataProvider();
for ( Binding<?> xmlBinding : managedResources.getXmlMappingBindings() ) {
Object root = xmlBinding.getRoot();
if ( !(root instanceof JaxbEntityMappings) ) {
continue;
}
JaxbEntityMappings entityMappings = (JaxbEntityMappings) xmlBinding.getRoot();
final List<String> classNames = jpaMetadataProvider.getXMLContext().addDocument( entityMappings );
for ( String className : classNames ) {
xClasses.add( toXClass( className, reflectionManager, classLoaderService ) );
}
final JPAXMLOverriddenMetadataProvider jpaMetadataProvider = (JPAXMLOverriddenMetadataProvider) ( (MetadataProviderInjector) reflectionManager )
.getMetadataProvider();
for ( Binding<?> xmlBinding : managedResources.getXmlMappingBindings() ) {
Object root = xmlBinding.getRoot();
if ( !(root instanceof JaxbEntityMappings) ) {
continue;
}
jpaMetadataProvider.getXMLContext().applyDiscoveredAttributeConverters( attributeConverterManager );
}
else {
final JPAMetadataProvider jpaMetadataProvider = (JPAMetadataProvider) ( (MetadataProviderInjector) reflectionManager )
.getMetadataProvider();
for ( Binding xmlBinding : managedResources.getXmlMappingBindings() ) {
if ( !org.dom4j.Document.class.isInstance( xmlBinding.getRoot() ) ) {
continue;
}
org.dom4j.Document dom4jDocument = (Document) xmlBinding.getRoot();
JaxbEntityMappings entityMappings = (JaxbEntityMappings) xmlBinding.getRoot();
final List<String> classNames = jpaMetadataProvider.getXMLContext().addDocument( dom4jDocument );
for ( String className : classNames ) {
xClasses.add( toXClass( className, reflectionManager, classLoaderService ) );
}
final List<String> classNames = jpaMetadataProvider.getXMLContext().addDocument( entityMappings );
for ( String className : classNames ) {
xClasses.add( toXClass( className, reflectionManager, classLoaderService ) );
}
jpaMetadataProvider.getXMLContext().applyDiscoveredAttributeConverters( attributeConverterManager );
}
jpaMetadataProvider.getXMLContext().applyDiscoveredAttributeConverters( attributeConverterManager );
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
}

View File

@ -41,12 +41,10 @@ public class XmlMappingBinderAccess {
public XmlMappingBinderAccess(ServiceRegistry serviceRegistry) {
this.classLoaderService = serviceRegistry.getService( ClassLoaderService.class );
XmlMappingOptions xmlMappingOptions = XmlMappingOptions.get( serviceRegistry );
// NOTE : The boolean here indicates whether or not to perform validation as we load XML documents.
// Should we expose this setting? Disabling would speed up JAXP and JAXB at runtime, but potentially
// at the cost of less obvious errors when a document is not valid.
this.mappingBinder = new MappingBinder( classLoaderService, true, xmlMappingOptions );
this.mappingBinder = new MappingBinder( classLoaderService, true );
}
public MappingBinder getMappingBinder() {

View File

@ -1,239 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.cfg.annotations.reflection;
import java.lang.reflect.AnnotatedElement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityListeners;
import javax.persistence.NamedNativeQuery;
import javax.persistence.NamedQuery;
import javax.persistence.NamedStoredProcedureQuery;
import javax.persistence.SequenceGenerator;
import javax.persistence.SqlResultSetMapping;
import javax.persistence.TableGenerator;
import org.hibernate.annotations.common.reflection.AnnotationReader;
import org.hibernate.annotations.common.reflection.MetadataProvider;
import org.hibernate.annotations.common.reflection.java.JavaMetadataProvider;
import org.hibernate.boot.internal.ClassLoaderAccessImpl;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.ClassLoaderAccess;
import org.hibernate.boot.spi.ClassLoaderAccessDelegateImpl;
import org.hibernate.boot.spi.MetadataBuildingOptions;
import org.hibernate.cfg.annotations.reflection.internal.JPAXMLOverriddenMetadataProvider;
import org.dom4j.Element;
/**
* MetadataProvider aware of the JPA Deployment descriptor
*
* @author Emmanuel Bernard
*
* @deprecated This class is not API: do not use it from application code.
* This class will be removed in Hibernate ORM 6.0.
* For implementation code, use {@link JPAXMLOverriddenMetadataProvider}
* instead.
*/
@Deprecated
@SuppressWarnings("unchecked")
public final class JPAMetadataProvider implements MetadataProvider {
private static final MetadataProvider STATELESS_BASE_DELEGATE = new JavaMetadataProvider();
private final ClassLoaderAccess classLoaderAccess;
private final XMLContext xmlContext;
/**
* We allow fully disabling XML sources so to improve the efficiency of
* the boot process for those not using it.
*/
private final boolean xmlMappingEnabled;
private Map<Object, Object> defaults;
private Map<AnnotatedElement, AnnotationReader> cache;
/**
* @deprecated Use {@link JPAMetadataProvider#JPAMetadataProvider(BootstrapContext)} instead.
*/
@Deprecated
public JPAMetadataProvider(final MetadataBuildingOptions metadataBuildingOptions) {
this( new ClassLoaderAccessDelegateImpl() {
ClassLoaderAccess delegate;
@Override
protected ClassLoaderAccess getDelegate() {
if ( delegate == null ) {
delegate = new ClassLoaderAccessImpl(
metadataBuildingOptions.getTempClassLoader(),
metadataBuildingOptions.getServiceRegistry().getService( ClassLoaderService.class )
);
}
return delegate;
}
},
metadataBuildingOptions.getXmlMappingOptions().isEnabled() );
}
public JPAMetadataProvider(BootstrapContext bootstrapContext) {
this( bootstrapContext.getClassLoaderAccess(),
bootstrapContext.getMetadataBuildingOptions().getXmlMappingOptions().isEnabled() );
}
JPAMetadataProvider(ClassLoaderAccess classLoaderAccess, boolean xmlMetadataEnabled) {
this.classLoaderAccess = classLoaderAccess;
this.xmlContext = new XMLContext( classLoaderAccess );
this.xmlMappingEnabled = xmlMetadataEnabled;
}
//all of the above can be safely rebuilt from XMLContext: only XMLContext this object is serialized
@Override
public AnnotationReader getAnnotationReader(AnnotatedElement annotatedElement) {
if ( cache == null ) {
cache = new HashMap<>(50 );
}
AnnotationReader reader = cache.get( annotatedElement );
if (reader == null) {
if ( xmlContext.hasContext() ) {
reader = new JPAOverriddenAnnotationReader( annotatedElement, xmlContext, classLoaderAccess );
}
else {
reader = STATELESS_BASE_DELEGATE.getAnnotationReader( annotatedElement );
}
cache.put( annotatedElement, reader );
}
return reader;
}
@Override
public void reset() {
//It's better to remove the HashMap, as it could grow rather large:
//when doing a clear() the internal buckets array is not scaled down.
this.cache = null;
}
@Override
public Map<Object, Object> getDefaults() {
if ( xmlMappingEnabled == false ) {
return Collections.emptyMap();
}
else {
if ( defaults == null ) {
defaults = new HashMap<>();
XMLContext.Default xmlDefaults = xmlContext.getDefault( null );
defaults.put( "schema", xmlDefaults.getSchema() );
defaults.put( "catalog", xmlDefaults.getCatalog() );
defaults.put( "delimited-identifier", xmlDefaults.getDelimitedIdentifier() );
defaults.put( "cascade-persist", xmlDefaults.getCascadePersist() );
List<Class> entityListeners = new ArrayList<Class>();
for ( String className : xmlContext.getDefaultEntityListeners() ) {
try {
entityListeners.add( classLoaderAccess.classForName( className ) );
}
catch ( ClassLoadingException e ) {
throw new IllegalStateException( "Default entity listener class not found: " + className );
}
}
defaults.put( EntityListeners.class, entityListeners );
for ( Element element : xmlContext.getAllDocuments() ) {
@SuppressWarnings( "unchecked" )
List<Element> elements = element.elements( "sequence-generator" );
List<SequenceGenerator> sequenceGenerators = ( List<SequenceGenerator> ) defaults.get( SequenceGenerator.class );
if ( sequenceGenerators == null ) {
sequenceGenerators = new ArrayList<>();
defaults.put( SequenceGenerator.class, sequenceGenerators );
}
for ( Element subelement : elements ) {
sequenceGenerators.add( JPAOverriddenAnnotationReader
.buildSequenceGeneratorAnnotation( subelement ) );
}
elements = element.elements( "table-generator" );
List<TableGenerator> tableGenerators = ( List<TableGenerator> ) defaults.get( TableGenerator.class );
if ( tableGenerators == null ) {
tableGenerators = new ArrayList<>();
defaults.put( TableGenerator.class, tableGenerators );
}
for ( Element subelement : elements ) {
tableGenerators.add(
JPAOverriddenAnnotationReader.buildTableGeneratorAnnotation(
subelement, xmlDefaults
)
);
}
List<NamedQuery> namedQueries = ( List<NamedQuery> ) defaults.get( NamedQuery.class );
if ( namedQueries == null ) {
namedQueries = new ArrayList<>();
defaults.put( NamedQuery.class, namedQueries );
}
List<NamedQuery> currentNamedQueries = JPAOverriddenAnnotationReader
.buildNamedQueries(
element,
false,
xmlDefaults,
classLoaderAccess
);
namedQueries.addAll( currentNamedQueries );
List<NamedNativeQuery> namedNativeQueries = ( List<NamedNativeQuery> ) defaults.get( NamedNativeQuery.class );
if ( namedNativeQueries == null ) {
namedNativeQueries = new ArrayList<>();
defaults.put( NamedNativeQuery.class, namedNativeQueries );
}
List<NamedNativeQuery> currentNamedNativeQueries = JPAOverriddenAnnotationReader
.buildNamedQueries(
element,
true,
xmlDefaults,
classLoaderAccess
);
namedNativeQueries.addAll( currentNamedNativeQueries );
List<SqlResultSetMapping> sqlResultSetMappings = ( List<SqlResultSetMapping> ) defaults.get(
SqlResultSetMapping.class
);
if ( sqlResultSetMappings == null ) {
sqlResultSetMappings = new ArrayList<>();
defaults.put( SqlResultSetMapping.class, sqlResultSetMappings );
}
List<SqlResultSetMapping> currentSqlResultSetMappings = JPAOverriddenAnnotationReader
.buildSqlResultsetMappings(
element,
xmlDefaults,
classLoaderAccess
);
sqlResultSetMappings.addAll( currentSqlResultSetMappings );
List<NamedStoredProcedureQuery> namedStoredProcedureQueries = (List<NamedStoredProcedureQuery>)defaults.get( NamedStoredProcedureQuery.class );
if(namedStoredProcedureQueries==null){
namedStoredProcedureQueries = new ArrayList<>( );
defaults.put( NamedStoredProcedureQuery.class, namedStoredProcedureQueries );
}
List<NamedStoredProcedureQuery> currentNamedStoredProcedureQueries = JPAOverriddenAnnotationReader
.buildNamedStoreProcedureQueries(
element,
xmlDefaults,
classLoaderAccess
);
namedStoredProcedureQueries.addAll( currentNamedStoredProcedureQueries );
}
}
return defaults;
}
}
public XMLContext getXMLContext() {
return xmlContext;
}
}

View File

@ -1,363 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.cfg.annotations.reflection;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.AccessType;
import javax.persistence.AttributeConverter;
import org.hibernate.AnnotationException;
import org.hibernate.boot.AttributeConverterInfo;
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.ClassLoaderAccess;
import org.hibernate.cfg.AttributeConverterDefinition;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
import org.dom4j.Document;
import org.dom4j.Element;
/**
* A helper for consuming orm.xml mappings.
*
* @author Emmanuel Bernard
* @author Brett Meyer
*
* @deprecated This class is not API: do not use it from application code.
* This class will be removed in Hibernate ORM 6.0.
* For implementation code, use {@link org.hibernate.cfg.annotations.reflection.internal.XMLContext} instead.
*/
@Deprecated
public class XMLContext implements Serializable {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( XMLContext.class );
private final ClassLoaderAccess classLoaderAccess;
private Default globalDefaults;
private Map<String, Element> classOverriding = new HashMap<>();
private Map<String, Default> defaultsOverriding = new HashMap<>();
private List<Element> defaultElements = new ArrayList<>();
private List<String> defaultEntityListeners = new ArrayList<>();
private boolean hasContext = false;
/**
* @deprecated Use {@link XMLContext#XMLContext(BootstrapContext)} instead.
*/
@Deprecated
public XMLContext(ClassLoaderAccess classLoaderAccess) {
this.classLoaderAccess = classLoaderAccess;
}
public XMLContext(BootstrapContext bootstrapContext) {
this.classLoaderAccess = bootstrapContext.getClassLoaderAccess();
}
/**
* @param doc The xml document to add
* @return Add an xml document to this context and return the list of added class names.
*/
@SuppressWarnings( "unchecked" )
public List<String> addDocument(Document doc) {
hasContext = true;
List<String> addedClasses = new ArrayList<>();
Element root = doc.getRootElement();
//global defaults
Element metadata = root.element( "persistence-unit-metadata" );
if ( metadata != null ) {
if ( globalDefaults == null ) {
globalDefaults = new Default();
globalDefaults.setMetadataComplete(
metadata.element( "xml-mapping-metadata-complete" ) != null ?
Boolean.TRUE :
null
);
Element defaultElement = metadata.element( "persistence-unit-defaults" );
if ( defaultElement != null ) {
Element unitElement = defaultElement.element( "schema" );
globalDefaults.setSchema( unitElement != null ? unitElement.getTextTrim() : null );
unitElement = defaultElement.element( "catalog" );
globalDefaults.setCatalog( unitElement != null ? unitElement.getTextTrim() : null );
unitElement = defaultElement.element( "access" );
setAccess( unitElement, globalDefaults );
unitElement = defaultElement.element( "cascade-persist" );
globalDefaults.setCascadePersist( unitElement != null ? Boolean.TRUE : null );
unitElement = defaultElement.element( "delimited-identifiers" );
globalDefaults.setDelimitedIdentifiers( unitElement != null ? Boolean.TRUE : null );
defaultEntityListeners.addAll( addEntityListenerClasses( defaultElement, null, addedClasses ) );
}
}
else {
LOG.duplicateMetadata();
}
}
//entity mapping default
Default entityMappingDefault = new Default();
Element unitElement = root.element( "package" );
String packageName = unitElement != null ? unitElement.getTextTrim() : null;
entityMappingDefault.setPackageName( packageName );
unitElement = root.element( "schema" );
entityMappingDefault.setSchema( unitElement != null ? unitElement.getTextTrim() : null );
unitElement = root.element( "catalog" );
entityMappingDefault.setCatalog( unitElement != null ? unitElement.getTextTrim() : null );
unitElement = root.element( "access" );
setAccess( unitElement, entityMappingDefault );
defaultElements.add( root );
setLocalAttributeConverterDefinitions( root.elements( "converter" ) );
List<Element> entities = root.elements( "entity" );
addClass( entities, packageName, entityMappingDefault, addedClasses );
entities = root.elements( "mapped-superclass" );
addClass( entities, packageName, entityMappingDefault, addedClasses );
entities = root.elements( "embeddable" );
addClass( entities, packageName, entityMappingDefault, addedClasses );
return addedClasses;
}
private void setAccess(Element unitElement, Default defaultType) {
if ( unitElement != null ) {
String access = unitElement.getTextTrim();
setAccess( access, defaultType );
}
}
private void setAccess( String access, Default defaultType) {
AccessType type;
if ( access != null ) {
try {
type = AccessType.valueOf( access );
}
catch ( IllegalArgumentException e ) {
throw new AnnotationException( "Invalid access type " + access + " (check your xml configuration)" );
}
defaultType.setAccess( type );
}
}
private void addClass(List<Element> entities, String packageName, Default defaults, List<String> addedClasses) {
for (Element element : entities) {
String className = buildSafeClassName( element.attributeValue( "class" ), packageName );
if ( classOverriding.containsKey( className ) ) {
//maybe switch it to warn?
throw new IllegalStateException( "Duplicate XML entry for " + className );
}
addedClasses.add( className );
classOverriding.put( className, element );
Default localDefault = new Default();
localDefault.override( defaults );
String metadataCompleteString = element.attributeValue( "metadata-complete" );
if ( metadataCompleteString != null ) {
localDefault.setMetadataComplete( Boolean.parseBoolean( metadataCompleteString ) );
}
String access = element.attributeValue( "access" );
setAccess( access, localDefault );
defaultsOverriding.put( className, localDefault );
LOG.debugf( "Adding XML overriding information for %s", className );
addEntityListenerClasses( element, packageName, addedClasses );
}
}
private List<String> addEntityListenerClasses(Element element, String packageName, List<String> addedClasses) {
List<String> localAddedClasses = new ArrayList<>();
Element listeners = element.element( "entity-listeners" );
if ( listeners != null ) {
@SuppressWarnings( "unchecked" )
List<Element> elements = listeners.elements( "entity-listener" );
for (Element listener : elements) {
String listenerClassName = buildSafeClassName( listener.attributeValue( "class" ), packageName );
if ( classOverriding.containsKey( listenerClassName ) ) {
//maybe switch it to warn?
if ( "entity-listener".equals( classOverriding.get( listenerClassName ).getName() ) ) {
LOG.duplicateListener( listenerClassName );
continue;
}
throw new IllegalStateException("Duplicate XML entry for " + listenerClassName);
}
localAddedClasses.add( listenerClassName );
classOverriding.put( listenerClassName, listener );
}
}
LOG.debugf( "Adding XML overriding information for listeners: %s", localAddedClasses );
addedClasses.addAll( localAddedClasses );
return localAddedClasses;
}
@SuppressWarnings("unchecked")
private void setLocalAttributeConverterDefinitions(List<Element> converterElements) {
for ( Element converterElement : converterElements ) {
final String className = converterElement.attributeValue( "class" );
final String autoApplyAttribute = converterElement.attributeValue( "auto-apply" );
final boolean autoApply = autoApplyAttribute != null && Boolean.parseBoolean( autoApplyAttribute );
try {
final Class<? extends AttributeConverter> attributeConverterClass = classLoaderAccess.classForName(
className
);
attributeConverterInfoList.add(
new AttributeConverterDefinition( attributeConverterClass.newInstance(), autoApply )
);
}
catch (ClassLoadingException e) {
throw new AnnotationException( "Unable to locate specified AttributeConverter implementation class : " + className, e );
}
catch (Exception e) {
throw new AnnotationException( "Unable to instantiate specified AttributeConverter implementation class : " + className, e );
}
}
}
public static String buildSafeClassName(String className, String defaultPackageName) {
if ( className.indexOf( '.' ) < 0 && StringHelper.isNotEmpty( defaultPackageName ) ) {
className = StringHelper.qualify( defaultPackageName, className );
}
return className;
}
public static String buildSafeClassName(String className, Default defaults) {
return buildSafeClassName( className, defaults.getPackageName() );
}
public Default getDefault(String className) {
Default xmlDefault = new Default();
xmlDefault.override( globalDefaults );
if ( className != null ) {
Default entityMappingOverriding = defaultsOverriding.get( className );
xmlDefault.override( entityMappingOverriding );
}
return xmlDefault;
}
public Element getXMLTree(String className ) {
return classOverriding.get( className );
}
public List<Element> getAllDocuments() {
return defaultElements;
}
public boolean hasContext() {
return hasContext;
}
private List<AttributeConverterInfo> attributeConverterInfoList = new ArrayList<>();
public void applyDiscoveredAttributeConverters(AttributeConverterDefinitionCollector collector) {
for ( AttributeConverterInfo info : attributeConverterInfoList ) {
collector.addAttributeConverter( info );
}
attributeConverterInfoList.clear();
}
public static class Default implements Serializable {
private AccessType access;
private String packageName;
private String schema;
private String catalog;
private Boolean metadataComplete;
private Boolean cascadePersist;
private Boolean delimitedIdentifier;
public AccessType getAccess() {
return access;
}
protected void setAccess(AccessType access) {
this.access = access;
}
public String getCatalog() {
return catalog;
}
protected void setCatalog(String catalog) {
this.catalog = catalog;
}
public String getPackageName() {
return packageName;
}
protected void setPackageName(String packageName) {
this.packageName = packageName;
}
public String getSchema() {
return schema;
}
protected void setSchema(String schema) {
this.schema = schema;
}
public Boolean getMetadataComplete() {
return metadataComplete;
}
public boolean canUseJavaAnnotations() {
return metadataComplete == null || !metadataComplete;
}
protected void setMetadataComplete(Boolean metadataComplete) {
this.metadataComplete = metadataComplete;
}
public Boolean getCascadePersist() {
return cascadePersist;
}
void setCascadePersist(Boolean cascadePersist) {
this.cascadePersist = cascadePersist;
}
public void override(Default globalDefault) {
if ( globalDefault != null ) {
if ( globalDefault.getAccess() != null ) {
access = globalDefault.getAccess();
}
if ( globalDefault.getPackageName() != null ) {
packageName = globalDefault.getPackageName();
}
if ( globalDefault.getSchema() != null ) {
schema = globalDefault.getSchema();
}
if ( globalDefault.getCatalog() != null ) {
catalog = globalDefault.getCatalog();
}
if ( globalDefault.getDelimitedIdentifier() != null ) {
delimitedIdentifier = globalDefault.getDelimitedIdentifier();
}
if ( globalDefault.getMetadataComplete() != null ) {
metadataComplete = globalDefault.getMetadataComplete();
}
//TODO fix that in stone if cascade-persist is set already?
if ( globalDefault.getCascadePersist() != null ) cascadePersist = globalDefault.getCascadePersist();
}
}
public void setDelimitedIdentifiers(Boolean delimitedIdentifier) {
this.delimitedIdentifier = delimitedIdentifier;
}
public Boolean getDelimitedIdentifier() {
return delimitedIdentifier;
}
}
public List<String> getDefaultEntityListeners() {
return defaultEntityListeners;
}
}

View File

@ -54,7 +54,7 @@ public class XMLContext implements Serializable {
private boolean hasContext = false;
/**
* @deprecated Use {@link org.hibernate.cfg.annotations.reflection.XMLContext#XMLContext(BootstrapContext)} instead.
* @deprecated Use {@link #XMLContext(BootstrapContext)} instead.
*/
@Deprecated
public XMLContext(ClassLoaderAccess classLoaderAccess) {

View File

@ -28,8 +28,8 @@ import org.junit.Assert;
public final class XMLMappingHelper {
private final MappingBinder binder;
public XMLMappingHelper(XmlMappingOptions xmlMappingOptions) {
binder = new MappingBinder( ClassLoaderServiceTestingImpl.INSTANCE, true, xmlMappingOptions );
public XMLMappingHelper() {
binder = new MappingBinder( ClassLoaderServiceTestingImpl.INSTANCE, true );
}
public JaxbEntityMappings readOrmXmlMappings(String name) throws IOException {

View File

@ -1,66 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.internal.util.xml;
import java.util.Collections;
import org.hibernate.boot.jaxb.spi.XmlMappingOptions;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.selector.SimpleStrategyRegistrationImpl;
import org.hibernate.boot.registry.selector.StrategyRegistration;
import org.hibernate.boot.registry.selector.StrategyRegistrationProvider;
import org.jboss.logging.Logger;
/**
* A strategy registration provider that allows running the whole test suite with different XML mapping options.
* <p>
* By default, this provider does nothing.
* In some CI jobs, we set the system property {@value STRATEGY_PROPERTY_KEY}
* to re-run the whole test suite using JAXB for orm.xml parsing instead of dom4j.
*/
public class XmlMappingOptionsStrategyRegistrationProvider implements StrategyRegistrationProvider {
protected final Logger log = Logger.getLogger( getClass() );
private static final String STRATEGY_PROPERTY_KEY = "testing.mapping.xml.strategy";
public static void applyJaxbStrategy(BootstrapServiceRegistryBuilder builder) {
builder.applyStrategySelector( XmlMappingOptions.class, XmlMappingOptions.DEFAULT_NAME,
PreferJaxbXmlMappingOptions.class
);
}
@Override
public Iterable<StrategyRegistration> getStrategyRegistrations() {
switch ( getStrategyFromSystemProperties() ) {
case "jaxb":
log.warn( "Overriding the default configuration because of a test system property:"
+ " will favor jaxb when parsing XML mapping." );
return Collections.singleton(
new SimpleStrategyRegistrationImpl<>( XmlMappingOptions.class,
PreferJaxbXmlMappingOptions.class,
XmlMappingOptions.DEFAULT_NAME )
);
case "default":
default:
return Collections.emptyList();
}
}
private static String getStrategyFromSystemProperties() {
String strategy = System.getProperty( STRATEGY_PROPERTY_KEY );
return strategy == null || strategy.isEmpty() ? "default" : strategy;
}
public static class PreferJaxbXmlMappingOptions implements XmlMappingOptions {
@Override
public boolean isPreferJaxb() {
return true;
}
}
}

View File

@ -7,7 +7,6 @@
package org.hibernate.test.annotations.reflection;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.internal.util.xml.XmlMappingOptionsStrategyRegistrationProvider;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
@ -22,7 +21,6 @@ public class ElementCollectionConverterTest extends BaseCoreFunctionalTestCase {
@Override
protected void prepareBootstrapRegistryBuilder(BootstrapServiceRegistryBuilder builder) {
super.prepareBootstrapRegistryBuilder( builder );
XmlMappingOptionsStrategyRegistrationProvider.applyJaxbStrategy( builder );
}
@Override

View File

@ -6,45 +6,25 @@
*/
package org.hibernate.test.annotations.reflection;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.hibernate.annotations.Columns;
import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityMappings;
import org.hibernate.boot.jaxb.spi.XmlMappingOptions;
import org.hibernate.cfg.EJB3DTDEntityResolver;
import org.hibernate.cfg.annotations.reflection.JPAOverriddenAnnotationReader;
import org.hibernate.cfg.annotations.reflection.internal.JPAXMLOverriddenAnnotationReader;
import org.hibernate.cfg.annotations.reflection.internal.XMLContext;
import org.hibernate.internal.util.xml.ErrorLogger;
import org.hibernate.internal.util.xml.XMLHelper;
import org.hibernate.internal.util.xml.XMLMappingHelper;
import org.hibernate.testing.boot.BootstrapContextImpl;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.boot.ClassLoaderServiceTestingImpl;
import org.junit.Test;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotSupportedException;
import javax.persistence.*;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import static org.junit.Assert.*;
/**
* Tests the new {@link JPAXMLOverriddenAnnotationReader},
* which will be replacing {@link JPAOverriddenAnnotationReader}.
* {@link JPAOverriddenAnnotationReader} is still the default implementation,
* but we want to switch to {@link JPAXMLOverriddenAnnotationReader}
* as soon as it will be practical.
*
* @see LegacyJPAOverriddenAnnotationReaderTest
* @author Emmanuel Bernard
*/
@TestForIssue(jiraKey = "HHH-14529")
@ -405,12 +385,7 @@ public class JPAXMLOverriddenAnnotationReaderTest extends BaseUnitTestCase {
}
private XMLContext buildContext(String ormfile) throws IOException {
XMLMappingHelper xmlHelper = new XMLMappingHelper( new XmlMappingOptions() {
@Override
public boolean isPreferJaxb() {
return true;
}
} );
XMLMappingHelper xmlHelper = new XMLMappingHelper();
JaxbEntityMappings mappings = xmlHelper.readOrmXmlMappings( ormfile );
XMLContext context = new XMLContext( BootstrapContextImpl.INSTANCE );
context.addDocument( mappings );

View File

@ -7,7 +7,6 @@
package org.hibernate.test.annotations.reflection;
import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityMappings;
import org.hibernate.boot.jaxb.spi.XmlMappingOptions;
import org.hibernate.cfg.annotations.reflection.internal.XMLContext;
import org.hibernate.internal.util.xml.XMLMappingHelper;
@ -16,24 +15,13 @@ import org.hibernate.testing.boot.BootstrapContextImpl;
import org.junit.Test;
/**
* Tests the new {@link XMLContext},
* which will be replacing {@link org.hibernate.cfg.annotations.reflection.XMLContext}.
* {@link org.hibernate.cfg.annotations.reflection.XMLContext} is still the default implementation,
* but we want to switch to {@link XMLContext}
* as soon as it will be practical.
*
* @author Emmanuel Bernard
*/
@TestForIssue(jiraKey = "HHH-14529")
public class XMLContextTest {
@Test
public void testAll() throws Exception {
XMLMappingHelper xmlHelper = new XMLMappingHelper( new XmlMappingOptions() {
@Override
public boolean isPreferJaxb() {
return true;
}
} );
XMLMappingHelper xmlHelper = new XMLMappingHelper();
final XMLContext context = new XMLContext( BootstrapContextImpl.INSTANCE );
JaxbEntityMappings mappings = xmlHelper.readOrmXmlMappings( "org/hibernate/test/annotations/reflection/orm.xml" );

View File

@ -17,7 +17,6 @@ import org.hibernate.dialect.CockroachDB192Dialect;
import org.hibernate.dialect.PostgreSQL81Dialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.TeradataDialect;
import org.hibernate.internal.util.xml.XmlMappingOptionsStrategyRegistrationProvider;
import org.hibernate.persister.collection.BasicCollectionPersister;
import org.hibernate.testing.SkipForDialect;
@ -37,7 +36,6 @@ public class Ejb3XmlTest extends BaseCoreFunctionalTestCase {
@Override
protected void prepareBootstrapRegistryBuilder(BootstrapServiceRegistryBuilder builder) {
super.prepareBootstrapRegistryBuilder( builder );
XmlMappingOptionsStrategyRegistrationProvider.applyJaxbStrategy( builder );
}
@Test

View File

@ -11,7 +11,6 @@ import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import org.hibernate.boot.jaxb.mapping.spi.JaxbEntityMappings;
import org.hibernate.boot.jaxb.spi.XmlMappingOptions;
import org.hibernate.cfg.annotations.reflection.internal.JPAXMLOverriddenAnnotationReader;
import org.hibernate.cfg.annotations.reflection.internal.XMLContext;
import org.hibernate.internal.util.xml.XMLMappingHelper;
@ -67,12 +66,7 @@ public abstract class Ejb3XmlTestCase extends BaseUnitTestCase {
}
protected XMLContext getContext(InputStream is, String resourceName) throws Exception {
XMLMappingHelper xmlHelper = new XMLMappingHelper( new XmlMappingOptions() {
@Override
public boolean isPreferJaxb() {
return true;
}
} );
XMLMappingHelper xmlHelper = new XMLMappingHelper();
JaxbEntityMappings mappings = xmlHelper.readOrmXmlMappings( is, resourceName );
XMLContext context = new XMLContext( BootstrapContextImpl.INSTANCE );
context.addDocument( mappings );

View File

@ -10,7 +10,6 @@ import org.hibernate.InvalidMappingException;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.internal.util.xml.UnsupportedOrmXsdVersionException;
import org.hibernate.internal.util.xml.XmlMappingOptionsStrategyRegistrationProvider;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseUnitTestCase;
@ -24,7 +23,6 @@ public class NonExistentOrmVersionTest extends BaseUnitTestCase {
public void testNonExistentOrmVersion() {
try {
BootstrapServiceRegistryBuilder builder = new BootstrapServiceRegistryBuilder();
XmlMappingOptionsStrategyRegistrationProvider.applyJaxbStrategy( builder );
new MetadataSources( builder.build() )
.addResource( "org/hibernate/test/annotations/xml/ejb3/orm5.xml" )
.buildMetadata();

View File

@ -11,7 +11,6 @@ import org.hibernate.Transaction;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.xml.ErrorLogger;
import org.hibernate.internal.util.xml.XmlMappingOptionsStrategyRegistrationProvider;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
@ -31,7 +30,6 @@ public class OrmVersion1SupportedTest extends BaseCoreFunctionalTestCase {
@Override
protected void prepareBootstrapRegistryBuilder(BootstrapServiceRegistryBuilder builder) {
super.prepareBootstrapRegistryBuilder( builder );
XmlMappingOptionsStrategyRegistrationProvider.applyJaxbStrategy( builder );
}
@Rule

View File

@ -13,7 +13,6 @@ import java.io.UncheckedIOException;
import org.hibernate.boot.jaxb.spi.Binding;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;
import org.hibernate.internal.util.xml.XmlMappingOptionsStrategyRegistrationProvider;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
@ -27,7 +26,6 @@ public class PreParsedOrmXmlTest extends BaseCoreFunctionalTestCase {
@Override
protected void prepareBootstrapRegistryBuilder(BootstrapServiceRegistryBuilder builder) {
super.prepareBootstrapRegistryBuilder( builder );
XmlMappingOptionsStrategyRegistrationProvider.applyJaxbStrategy( builder );
}
@Override

View File

@ -1 +0,0 @@
org.hibernate.internal.util.xml.XmlMappingOptionsStrategyRegistrationProvider