From 047d3086018c398ce121b154d7128ecf8c6d4ba4 Mon Sep 17 00:00:00 2001 From: Brett Meyer Date: Wed, 21 May 2014 17:12:24 -0400 Subject: [PATCH] HHH-8893 delay binding of xml resources until building Metadata, introduce ClassLoaderAccess into transformer, removed old XmlBinder --- .../hibernate/metamodel/MetadataSources.java | 44 ++-- .../internal/ClassLoaderAccessImpl.java | 5 +- .../internal/MetadataBuildingProcess.java | 6 +- .../internal/jandex/EntityMappingsMocker.java | 26 --- .../internal/jaxb/hbm/HbmXmlTransformer.java | 8 +- .../xml/internal/jaxb/AbstractXmlBinder.java | 195 ------------------ .../internal/jaxb/ConfigurationXmlBinder.java | 85 -------- .../xml/internal/jaxb/MappingXmlBinder.java | 156 -------------- .../internal/jaxb/UnifiedMappingBinder.java | 11 +- .../org/hibernate/xml/spi/BindResult.java | 76 ++++++- .../java/org/hibernate/xml/spi/XmlBinder.java | 33 --- .../xml/mocker/AbstractMockerTest.java | 31 +-- .../annotations/xml/mocker/XmlHelper.java | 79 ------- .../unified/jaxb/SimpleBindingTest.java | 16 +- 14 files changed, 131 insertions(+), 640 deletions(-) delete mode 100644 hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/AbstractXmlBinder.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/ConfigurationXmlBinder.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/MappingXmlBinder.java delete mode 100644 hibernate-core/src/main/java/org/hibernate/xml/spi/XmlBinder.java delete mode 100644 hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/XmlHelper.java diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataSources.java b/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataSources.java index 3724cd5f77..adbc635c0c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataSources.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/MetadataSources.java @@ -61,9 +61,9 @@ import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings; import org.hibernate.metamodel.source.internal.jaxb.JaxbMappedSuperclass; import org.hibernate.metamodel.source.internal.jaxb.JaxbPersistenceUnitDefaults; import org.hibernate.metamodel.source.internal.jaxb.JaxbPersistenceUnitMetadata; -import org.hibernate.metamodel.source.spi.InvalidMappingException; import org.hibernate.metamodel.source.spi.MappingException; import org.hibernate.metamodel.source.spi.MappingNotFoundException; +import org.hibernate.metamodel.spi.ClassLoaderAccess; import org.hibernate.service.ServiceRegistry; import org.hibernate.type.SerializationException; import org.hibernate.xml.internal.jaxb.UnifiedMappingBinder; @@ -86,7 +86,6 @@ public class MetadataSources { private static final CoreMessageLogger LOG = CoreLogging.messageLogger( MetadataSources.class ); private final ServiceRegistry serviceRegistry; - private final UnifiedMappingBinder jaxbProcessor; private List bindResultList = new ArrayList(); private LinkedHashSet> annotatedClasses = new LinkedHashSet>(); private LinkedHashSet annotatedClassNames = new LinkedHashSet(); @@ -94,8 +93,6 @@ public class MetadataSources { private List> converterClasses; - private boolean hasOrmXmlJaxbRoots; - public MetadataSources() { this( new BootstrapServiceRegistryBuilder().build() ); } @@ -115,13 +112,19 @@ public class MetadataSources { ); } this.serviceRegistry = serviceRegistry; - this.jaxbProcessor = new UnifiedMappingBinder(); } protected static boolean isExpectedServiceRegistryType(ServiceRegistry serviceRegistry) { return BootstrapServiceRegistry.class.isInstance( serviceRegistry ) || StandardServiceRegistry.class.isInstance( serviceRegistry ); } + + public void buildBindResults(ClassLoaderAccess classLoaderAccess) { + final UnifiedMappingBinder jaxbProcessor = new UnifiedMappingBinder( classLoaderAccess ); + for ( BindResult bindResult : bindResultList ) { + bindResult.bind( jaxbProcessor ); + } + } public List getBindResultList() { return bindResultList; @@ -243,24 +246,9 @@ public class MetadataSources { } private BindResult add(InputStream inputStream, Origin origin, boolean close) { - try { - BindResult bindResult = new BindResult( jaxbProcessor.bind( inputStream, origin ), origin ); - addJaxbRoot( bindResult ); - return bindResult; - } - catch ( Exception e ) { - throw new InvalidMappingException( origin, e ); - } - finally { - if ( close ) { - try { - inputStream.close(); - } - catch ( IOException ignore ) { - LOG.trace( "Was unable to close input stream" ); - } - } - } + BindResult bindResult = new BindResult( inputStream, origin, close ); + bindResultList.add( bindResult ); + return bindResult; } /** @@ -419,7 +407,7 @@ public class MetadataSources { } LOG.readingCachedMappings( cachedFile ); - addJaxbRoot( (BindResult) SerializationHelper.deserialize( new FileInputStream( cachedFile ) ) ); + bindResultList.add( (BindResult) SerializationHelper.deserialize( new FileInputStream( cachedFile ) ) ); return this; } @@ -470,16 +458,10 @@ public class MetadataSources { @Deprecated public MetadataSources addDocument(Document document) { final Origin origin = new Origin( SourceType.DOM, Origin.UNKNOWN_FILE_PATH ); - BindResult bindResult = new BindResult( jaxbProcessor.bind( new DOMSource( document ), origin ), origin ); - addJaxbRoot( bindResult ); + bindResultList.add( new BindResult( new DOMSource( document ), origin ) ); return this; } - private void addJaxbRoot(BindResult bindResult) { - hasOrmXmlJaxbRoots = hasOrmXmlJaxbRoots || JaxbEntityMappings.class.isInstance( bindResult.getRoot() ); - bindResultList.add( bindResult ); - } - /** * Read all mappings from a jar file. *

diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ClassLoaderAccessImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ClassLoaderAccessImpl.java index e6d720dfee..5e808abf87 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ClassLoaderAccessImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/ClassLoaderAccessImpl.java @@ -25,11 +25,10 @@ package org.hibernate.metamodel.internal; import java.net.URL; -import org.hibernate.boot.registry.StandardServiceRegistry; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; import org.hibernate.metamodel.spi.ClassLoaderAccess; - +import org.hibernate.service.ServiceRegistry; import org.jboss.logging.Logger; /** @@ -48,7 +47,7 @@ public class ClassLoaderAccessImpl implements ClassLoaderAccess { this.classLoaderService = classLoaderService; } - public ClassLoaderAccessImpl(ClassLoader tempClassLoader, StandardServiceRegistry serviceRegistry) { + public ClassLoaderAccessImpl(ClassLoader tempClassLoader, ServiceRegistry serviceRegistry) { this( tempClassLoader, serviceRegistry.getService( ClassLoaderService.class ) ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataBuildingProcess.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataBuildingProcess.java index 7e545271ee..d6040d37e6 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataBuildingProcess.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataBuildingProcess.java @@ -148,9 +148,13 @@ public class MetadataBuildingProcess { options.getTempClassLoader(), options.getServiceRegistry() ); + + // It's necessary to delay the binding of XML resources until now. ClassLoaderAccess is needed for + // reflection, etc. + sources.buildBindResults( classLoaderAccess ); final JandexInitManager jandexInitializer = buildJandexInitializer( options, classLoaderAccess ); - + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // scanning - Jandex initialization and source discovery if ( options.getScanEnvironment() != null ) { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EntityMappingsMocker.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EntityMappingsMocker.java index 8aba723f01..5288005057 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EntityMappingsMocker.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jandex/EntityMappingsMocker.java @@ -39,8 +39,6 @@ import org.hibernate.metamodel.source.internal.jaxb.JaxbPersistenceUnitDefaults; import org.hibernate.metamodel.source.internal.jaxb.JaxbPersistenceUnitMetadata; import org.hibernate.service.ServiceRegistry; import org.hibernate.xml.spi.BindResult; -import org.hibernate.xml.spi.Origin; -import org.hibernate.xml.spi.SourceType; import org.jboss.jandex.Index; import org.jboss.jandex.IndexView; @@ -68,30 +66,6 @@ public class EntityMappingsMocker { this.globalAnnotations = new GlobalAnnotations(); } - public EntityMappingsMocker( - List xmlEntityMappingsList, - Index index, - ServiceRegistry serviceRegistry) { - this( - grabJaxbEntityMappings( xmlEntityMappingsList ), - index, - serviceRegistry - ); - } - - private static List> grabJaxbEntityMappings(List xmlEntityMappingsList) { - final List> result = new ArrayList>(); - for ( JaxbEntityMappings binding : xmlEntityMappingsList ) { - result.add( - new BindResult( - binding, - new Origin( SourceType.OTHER, Origin.UNKNOWN_FILE_PATH ) - ) - ); - } - return result; - } - /** * Create new {@link Index} with mocking JPA annotations from {@link org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings} * and merge them with existing {@link Index} diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/HbmXmlTransformer.java b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/HbmXmlTransformer.java index 930548d919..532b515f70 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/HbmXmlTransformer.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/source/internal/jaxb/hbm/HbmXmlTransformer.java @@ -30,7 +30,6 @@ import javax.xml.bind.JAXBElement; import org.hibernate.FlushMode; import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.internal.jandex.MockHelper; import org.hibernate.metamodel.source.internal.jaxb.JaxbAny; import org.hibernate.metamodel.source.internal.jaxb.JaxbAttributes; import org.hibernate.metamodel.source.internal.jaxb.JaxbBasic; @@ -62,7 +61,6 @@ import org.hibernate.metamodel.source.internal.jaxb.JaxbHbmTypeDef; import org.hibernate.metamodel.source.internal.jaxb.JaxbId; import org.hibernate.metamodel.source.internal.jaxb.JaxbIdClass; import org.hibernate.metamodel.source.internal.jaxb.JaxbJoinColumn; -import org.hibernate.metamodel.source.internal.jaxb.JaxbJoinTable; import org.hibernate.metamodel.source.internal.jaxb.JaxbManyToOne; import org.hibernate.metamodel.source.internal.jaxb.JaxbNamedNativeQuery; import org.hibernate.metamodel.source.internal.jaxb.JaxbNamedQuery; @@ -72,6 +70,7 @@ import org.hibernate.metamodel.source.internal.jaxb.JaxbPersistenceUnitMetadata; import org.hibernate.metamodel.source.internal.jaxb.JaxbQueryParamType; import org.hibernate.metamodel.source.internal.jaxb.JaxbSynchronizeType; import org.hibernate.metamodel.source.internal.jaxb.JaxbTable; +import org.hibernate.metamodel.spi.ClassLoaderAccess; import org.hibernate.xml.spi.Origin; import org.jboss.logging.Logger; @@ -91,9 +90,12 @@ public class HbmXmlTransformer { private Origin origin; private JaxbEntityMappings ormRoot; + private ClassLoaderAccess classLoaderAccess; - public JaxbEntityMappings transform(JaxbHibernateMapping hbmXmlMapping, Origin origin) { + public JaxbEntityMappings transform(JaxbHibernateMapping hbmXmlMapping, Origin origin, + ClassLoaderAccess classLoaderAccess) { this.origin = origin; + this.classLoaderAccess = classLoaderAccess; ormRoot = new JaxbEntityMappings(); ormRoot.setDescription( diff --git a/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/AbstractXmlBinder.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/AbstractXmlBinder.java deleted file mode 100644 index ea08f76af9..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/AbstractXmlBinder.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2013, 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 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 - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.xml.internal.jaxb; - -import java.io.InputStream; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.events.StartElement; -import javax.xml.stream.events.XMLEvent; -import javax.xml.validation.Schema; - -import org.hibernate.metamodel.source.spi.MappingException; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.xml.internal.stax.BufferedXMLEventReader; -import org.hibernate.xml.internal.stax.LocalXmlResourceResolver; -import org.hibernate.xml.spi.BindResult; -import org.hibernate.xml.spi.Origin; -import org.hibernate.xml.spi.XmlBinder; - -import org.jboss.logging.Logger; - -/** - * Base implementation (template) of the XmlBinder contract. - *

- * Generally implementors should just have to implement:

    - *
  1. {@link #getJaxbContext}
  2. - *
  3. {@link #getSchema}
  4. - *
  5. (optionally) {@link #wrapReader}
  6. - *
- * - * @author Steve Ebersole - * @author Strong Liu - * - * @deprecated See {@link AbstractUnifiedBinder} - */ -@Deprecated -abstract class AbstractXmlBinder implements XmlBinder { - protected static final Logger log = Logger.getLogger( AbstractXmlBinder.class ); - - protected final ServiceRegistry serviceRegistry; - protected final boolean validateXml; - - public AbstractXmlBinder(ServiceRegistry serviceRegistry) { - this( serviceRegistry, true ); - } - - public AbstractXmlBinder(ServiceRegistry serviceRegistry, boolean validateXml) { - this.serviceRegistry = serviceRegistry; - this.validateXml = validateXml; - } - - @Override - public BindResult bind(InputStream stream, Origin origin) { - try { - BufferedXMLEventReader staxReader = new BufferedXMLEventReader(staxFactory().createXMLEventReader( stream ), 100); - try { - return unmarshal( staxReader, origin ); - } - finally { - try { - staxReader.close(); - } - catch ( Exception ignore ) { - } - } - } - catch ( XMLStreamException e ) { - throw new MappingException( "Unable to create stax reader", e, origin ); - } - } - - private XMLInputFactory staxFactory; - - private XMLInputFactory staxFactory() { - if ( staxFactory == null ) { - staxFactory = buildStaxFactory(); - } - return staxFactory; - } - - @SuppressWarnings( { "UnnecessaryLocalVariable" }) - private XMLInputFactory buildStaxFactory() { - XMLInputFactory staxFactory = XMLInputFactory.newInstance(); - staxFactory.setXMLResolver( LocalXmlResourceResolver.INSTANCE ); - return staxFactory; - } - - @SuppressWarnings( { "unchecked" }) - private BindResult unmarshal(XMLEventReader staxEventReader, final Origin origin) { - XMLEvent rootElementStartEvent; - try { - rootElementStartEvent = staxEventReader.peek(); - while ( rootElementStartEvent != null && !rootElementStartEvent.isStartElement() ) { - staxEventReader.nextEvent(); - rootElementStartEvent = staxEventReader.peek(); - } - } - catch ( Exception e ) { - throw new MappingException( "Error accessing stax stream", e, origin ); - } - - if ( rootElementStartEvent == null ) { - throw new MappingException( "Could not locate root element", origin ); - } - - - final ContextProvidingValidationEventHandler handler = new ContextProvidingValidationEventHandler(); - try { - final Schema schema = getSchema( rootElementStartEvent, origin ); - staxEventReader = wrapReader( staxEventReader, rootElementStartEvent ); - - final JAXBContext jaxbContext = getJaxbContext( rootElementStartEvent ); - final Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); - unmarshaller.setSchema( schema ); - unmarshaller.setEventHandler( handler ); - - final Object target = unmarshaller.unmarshal( staxEventReader ); - return new BindResult( target, origin ); - } - catch ( JAXBException e ) { - throw new MappingException( - "Unable to perform unmarshalling at line number " + handler.getLineNumber() - + " and column " + handler.getColumnNumber() - + ". Message: " + handler.getMessage(), - e, - origin - ); - } - } - - /** - * Identify the Schema to use to validate the document being processed. - * - * @param rootElementStartEvent The peeked event that represents the start of the root element of the document - * @param origin - * - * @return - * - * @throws JAXBException - */ - protected abstract Schema getSchema(XMLEvent rootElementStartEvent, Origin origin) throws JAXBException; - - /** - * Wrap the given StAX event reader in another if needed. - * - * @param xmlEventReader The "real" reader. - * @param rootElementStartEvent The peeked event that represents the start of the root element of the document - * - * @return The wrapped reader. Simply return the given reader if no wrapping is needed. - */ - protected XMLEventReader wrapReader(XMLEventReader xmlEventReader, XMLEvent rootElementStartEvent) { - return xmlEventReader; - } - - /** - * Get the JAXB context representing the Java model to bind to. - * - * @param event - * - * @return - * - * @throws JAXBException - */ - protected abstract JAXBContext getJaxbContext(XMLEvent event) throws JAXBException; - - protected static boolean isNamespaced(StartElement startElement) { - return ! "".equals( startElement.getName().getNamespaceURI() ); - } - -} diff --git a/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/ConfigurationXmlBinder.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/ConfigurationXmlBinder.java deleted file mode 100644 index 19cd950813..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/ConfigurationXmlBinder.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, 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 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 - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.xml.internal.jaxb; - -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.events.XMLEvent; -import javax.xml.validation.Schema; - -import org.jboss.logging.Logger; - -import org.hibernate.xml.internal.stax.LocalSchemaLocator; -import org.hibernate.xml.spi.Origin; -import org.hibernate.jaxb.spi.cfg.JaxbHibernateConfiguration; -import org.hibernate.service.ServiceRegistry; - -/** - * @author Steve Ebersole - */ -public class ConfigurationXmlBinder extends AbstractXmlBinder { - private static final Logger log = Logger.getLogger( ConfigurationXmlBinder.class ); - - public static final String HIBERNATE_CONFIGURATION_URI = "http://www.hibernate.org/xsd/hibernate-configuration"; - - - public ConfigurationXmlBinder(ServiceRegistry serviceRegistry) { - this( serviceRegistry, true ); - } - - public ConfigurationXmlBinder(ServiceRegistry serviceRegistry, boolean validateXml) { - super(serviceRegistry, validateXml); - } - - @Override - protected XMLEventReader wrapReader(XMLEventReader xmlEventReader, XMLEvent event) { - if ( !isNamespaced( event.asStartElement() ) ) { - // if the elements are not namespaced, wrap the reader in a reader which will namespace them as pulled. - log.debug( "cfg.xml document did not define namespaces; wrapping in custom event reader to introduce namespace information" ); - return new NamespaceAddingEventReader( xmlEventReader, HIBERNATE_CONFIGURATION_URI ); - } - return super.wrapReader( xmlEventReader, event ); - } - - @Override - protected JAXBContext getJaxbContext(XMLEvent event) throws JAXBException{ - return JAXBContext.newInstance( JaxbHibernateConfiguration.class ); - } - - @Override - protected Schema getSchema(XMLEvent event, Origin origin) throws JAXBException { - if ( schema == null ) { - schema = LocalSchemaLocator.resolveLocalSchema( "org/hibernate/hibernate-configuration-4.0.xsd" ); - } - return schema; - } - - private Schema schema; - - - - - -} diff --git a/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/MappingXmlBinder.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/MappingXmlBinder.java deleted file mode 100644 index f5302a60e8..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/MappingXmlBinder.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, 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 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 - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.xml.internal.jaxb; - -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.events.XMLEvent; -import javax.xml.transform.dom.DOMSource; -import javax.xml.validation.Schema; - -import org.hibernate.internal.util.StringHelper; -import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings; -import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbHibernateMapping; -import org.hibernate.metamodel.source.spi.MappingException; -import org.hibernate.service.ServiceRegistry; -import org.hibernate.xml.internal.stax.LocalSchema; -import org.hibernate.xml.internal.stax.SupportedOrmXsdVersion; -import org.hibernate.xml.spi.BindResult; -import org.hibernate.xml.spi.Origin; - -import org.w3c.dom.Document; -import org.w3c.dom.Element; - -/** - * Loads {@code hbm.xml} and {@code orm.xml} files and processes them using StAX and JAXB. - * - * @author Steve Ebersole - * @author Hardy Ferentschik - * - * @deprecated see {@link org.hibernate.xml.internal.jaxb.UnifiedMappingBinder} - */ -@Deprecated -public class MappingXmlBinder extends AbstractXmlBinder { - public MappingXmlBinder(ServiceRegistry serviceRegistry) { - this( serviceRegistry, true ); - } - - public MappingXmlBinder(ServiceRegistry serviceRegistry, boolean validateXml) { - super(serviceRegistry, validateXml); - } - - @Override - protected JAXBContext getJaxbContext(XMLEvent event) throws JAXBException { - final String elementName = event.asStartElement().getName().getLocalPart(); - final Class jaxbTarget; - if ( "entity-mappings".equals( elementName ) ) { - jaxbTarget = JaxbEntityMappings.class; - } - else { - jaxbTarget = JaxbHibernateMapping.class; - } - return JAXBContext.newInstance( jaxbTarget ); - } - - @Override - protected Schema getSchema(XMLEvent event, Origin origin) throws JAXBException { - final String elementName = event.asStartElement().getName().getLocalPart(); - final Schema validationSchema; - if ( "entity-mappings".equals( elementName ) ) { - return LocalSchema.MAPPING.getSchema(); - } - else { - validationSchema = validateXml ? SupportedOrmXsdVersion.HBM_4_0.getSchema() : null; - } - return validationSchema; - } - - @Override - protected XMLEventReader wrapReader(XMLEventReader staxEventReader, XMLEvent event) { - final String elementName = event.asStartElement().getName().getLocalPart(); - if ( "entity-mappings".equals( elementName ) ) { - return new UnifiedMappingEventReader( staxEventReader ); - } - else { - return new HbmEventReader( staxEventReader ); - } - } - - - @SuppressWarnings( { "unchecked" }) - public BindResult bind(Document document, Origin origin) { - Element rootElement = document.getDocumentElement(); - if ( rootElement == null ) { - throw new MappingException( "No root element found", origin ); - } - - final Schema validationSchema; - final Class jaxbTarget; - - if ( "entity-mappings".equals( rootElement.getNodeName() ) ) { - final String explicitVersion = rootElement.getAttribute( "version" ); - validationSchema = validateXml ? resolveSupportedOrmXsd( explicitVersion, origin ) : null; - jaxbTarget = JaxbEntityMappings.class; - } - else { - validationSchema = validateXml ? SupportedOrmXsdVersion.HBM_4_0.getSchema() : null; - jaxbTarget = JaxbHibernateMapping.class; - } - - final Object target; - try { - JAXBContext jaxbContext = JAXBContext.newInstance( jaxbTarget ); - Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); - unmarshaller.setSchema( validationSchema ); - target = unmarshaller.unmarshal( new DOMSource( document ) ); - } - catch ( JAXBException e ) { - throw new MappingException( "Unable to perform unmarshalling", e, origin ); - } - - return new BindResult( target, origin ); - } - - private Schema resolveSupportedOrmXsd(String explicitVersion, Origin origin) { - if ( StringHelper.isEmpty( explicitVersion ) ) { - return SupportedOrmXsdVersion.ORM_2_1.getSchema(); - } - - // Here we always use JPA 2.1 schema to do the validation, since the {@link LegacyJPAEventReader} already - // transforms the legacy orm.xml to JPA 2.1 namespace and version. - // - // This may cause some problems, like a jpa 1.0 orm.xml having some element which is only available in the later - // version. It is "invalid" but due to the fact we're using the latest schema to do the validation, then - // it is "valid". Don't know if this will cause any problems, but let's do it for now. - // - // However, still check for the validity of the version by calling #parse. If someone explicitly uses a value - // that doesn't exist, we still need to throw the exception. - SupportedOrmXsdVersion.parse( explicitVersion, origin ); - - return SupportedOrmXsdVersion.ORM_2_1.getSchema(); - - } -} diff --git a/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/UnifiedMappingBinder.java b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/UnifiedMappingBinder.java index 22cdd3390c..68ee924ad3 100644 --- a/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/UnifiedMappingBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/xml/internal/jaxb/UnifiedMappingBinder.java @@ -29,6 +29,7 @@ import javax.xml.stream.events.StartElement; import org.hibernate.metamodel.source.internal.jaxb.hbm.JaxbHibernateMapping; import org.hibernate.metamodel.source.internal.jaxb.hbm.HbmXmlTransformer; import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings; +import org.hibernate.metamodel.spi.ClassLoaderAccess; import org.hibernate.xml.internal.stax.LocalSchema; import org.hibernate.xml.spi.Origin; @@ -41,13 +42,17 @@ import org.jboss.logging.Logger; */ public class UnifiedMappingBinder extends AbstractUnifiedBinder { private static final Logger log = Logger.getLogger( UnifiedMappingBinder.class ); + + private final ClassLoaderAccess classLoaderAccess; - public UnifiedMappingBinder() { + public UnifiedMappingBinder(ClassLoaderAccess classLoaderAccess) { super(); + this.classLoaderAccess = classLoaderAccess; } - public UnifiedMappingBinder(boolean validateXml) { + public UnifiedMappingBinder(boolean validateXml, ClassLoaderAccess classLoaderAccess) { super( validateXml ); + this.classLoaderAccess = classLoaderAccess; } @Override @@ -65,7 +70,7 @@ public class UnifiedMappingBinder extends AbstractUnifiedBinder implements Serializable { - private final T root; + private static final Logger LOG = CoreLogging.logger( BindResult.class ); + + private final DelayedBinder binder; + private final Origin origin; + + private final boolean close; + + private T root; - public BindResult(T root, Origin origin) { - this.root = root; + public BindResult(Source source, Origin origin) { + binder = new DelayedSourceBinder( source ); this.origin = origin; + close = false; + } + + public BindResult(InputStream inputStream, Origin origin, boolean close) { + binder = new DelayedInputStreamBinder( inputStream ); + this.origin = origin; + this.close = close; + } + + public void bind(AbstractUnifiedBinder jaxbProcessor) { + root = binder.bind( jaxbProcessor ); } /** @@ -57,4 +84,47 @@ public class BindResult implements Serializable { public Origin getOrigin() { return origin; } + + private interface DelayedBinder { + public T bind(AbstractUnifiedBinder jaxbProcessor); + } + + private class DelayedSourceBinder implements DelayedBinder { + private final Source source; + + public DelayedSourceBinder(Source source) { + this.source = source; + } + + public T bind(AbstractUnifiedBinder jaxbProcessor) { + return jaxbProcessor.bind( source, origin ); + } + } + + private class DelayedInputStreamBinder implements DelayedBinder { + private final InputStream inputStream; + + public DelayedInputStreamBinder(InputStream inputStream) { + this.inputStream = inputStream; + } + + public T bind(AbstractUnifiedBinder jaxbProcessor) { + try { + return jaxbProcessor.bind( inputStream, origin ); + } + catch ( Exception e ) { + throw new InvalidMappingException( origin, e ); + } + finally { + if ( close ) { + try { + inputStream.close(); + } + catch ( IOException ignore ) { + LOG.trace( "Was unable to close input stream" ); + } + } + } + } + } } diff --git a/hibernate-core/src/main/java/org/hibernate/xml/spi/XmlBinder.java b/hibernate-core/src/main/java/org/hibernate/xml/spi/XmlBinder.java deleted file mode 100644 index a1421ea539..0000000000 --- a/hibernate-core/src/main/java/org/hibernate/xml/spi/XmlBinder.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2014, 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 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 - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.xml.spi; - -import java.io.InputStream; - -/** - * @author Steve Ebersole - */ -public interface XmlBinder { - public BindResult bind(InputStream stream, Origin origin); -} diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AbstractMockerTest.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AbstractMockerTest.java index c9571b4e15..77708590d9 100644 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AbstractMockerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/AbstractMockerTest.java @@ -23,6 +23,9 @@ */ package org.hibernate.metamodel.internal.source.annotations.xml.mocker; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; @@ -30,17 +33,16 @@ import java.util.List; import org.hibernate.HibernateException; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings; +import org.hibernate.metamodel.internal.ClassLoaderAccessImpl; import org.hibernate.metamodel.source.internal.jandex.EntityMappingsMocker; import org.hibernate.metamodel.source.internal.jandex.IndexBuilder; +import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings; import org.hibernate.service.ServiceRegistry; -import org.hibernate.xml.internal.jaxb.MappingXmlBinder; +import org.hibernate.testing.ServiceRegistryBuilder; +import org.hibernate.xml.internal.jaxb.UnifiedMappingBinder; import org.hibernate.xml.spi.BindResult; import org.hibernate.xml.spi.Origin; import org.hibernate.xml.spi.SourceType; - -import org.hibernate.testing.ServiceRegistryBuilder; - import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.ClassInfo; @@ -48,9 +50,6 @@ import org.jboss.jandex.DotName; import org.jboss.jandex.Index; import org.jboss.jandex.Indexer; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; - /** * @author Strong Liu */ @@ -72,18 +71,20 @@ public abstract class AbstractMockerTest { } protected EntityMappingsMocker getEntityMappingsMocker(String... mappingFiles) { - MappingXmlBinder processor = new MappingXmlBinder( getServiceRegistry() ); + UnifiedMappingBinder processor = new UnifiedMappingBinder( + new ClassLoaderAccessImpl(null, getServiceRegistry() ) ); ClassLoaderService classLoaderService = getServiceRegistry().getService( ClassLoaderService.class ); - List xmlEntityMappingsList = new ArrayList(); + List> xmlBindings = new ArrayList>(); for ( String fileName : mappingFiles ) { - BindResult bindResult = processor.bind( + BindResult bindResult = new BindResult( classLoaderService.locateResourceStream( packagePrefix + fileName ), - new Origin( SourceType.FILE, packagePrefix + fileName ) + new Origin( SourceType.FILE, packagePrefix + fileName ), + true ); - JaxbEntityMappings entityMappings = (JaxbEntityMappings) bindResult.getRoot(); - xmlEntityMappingsList.add( entityMappings ); + bindResult.bind( processor ); + xmlBindings.add( bindResult ); } - return new EntityMappingsMocker( xmlEntityMappingsList, getIndex(), getServiceRegistry() ); + return new EntityMappingsMocker( xmlBindings, getIndex(), getServiceRegistry() ); } protected Index getIndex() { diff --git a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/XmlHelper.java b/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/XmlHelper.java deleted file mode 100644 index 063aa9f70c..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/metamodel/internal/source/annotations/xml/mocker/XmlHelper.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Hibernate, Relational Persistence for Idiomatic Java - * - * Copyright (c) 2011, 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 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 - * Lesser General Public License, as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this distribution; if not, write to: - * Free Software Foundation, Inc. - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301 USA - */ -package org.hibernate.metamodel.internal.source.annotations.xml.mocker; - -import java.io.InputStream; -import java.net.URL; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.JAXBException; -import javax.xml.bind.Unmarshaller; -import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; - -import org.jboss.logging.Logger; -import org.xml.sax.SAXException; - -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.internal.CoreMessageLogger; -import org.hibernate.xml.spi.BindResult; -import org.hibernate.xml.spi.Origin; - -/** - * @author Hardy Ferentschik - */ -public class XmlHelper { - private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, XmlHelper.class.getName() ); - - private XmlHelper() { - } - - public static BindResult unmarshallXml(String fileName, String schemaName, Class clazz, ClassLoaderService classLoaderService) - throws JAXBException { - Schema schema = getMappingSchema( schemaName, classLoaderService ); - InputStream in = classLoaderService.locateResourceStream( fileName ); - JAXBContext jc = JAXBContext.newInstance( clazz ); - Unmarshaller unmarshaller = jc.createUnmarshaller(); - unmarshaller.setSchema( schema ); - StreamSource stream = new StreamSource( in ); - JAXBElement elem = unmarshaller.unmarshal( stream, clazz ); - Origin origin = new Origin( null, fileName ); - return new BindResult( elem.getValue(), origin ); - } - - private static Schema getMappingSchema(String schemaVersion, ClassLoaderService classLoaderService) { - URL schemaUrl = classLoaderService.locateResource( schemaVersion ); - SchemaFactory sf = SchemaFactory.newInstance( javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI ); - Schema schema = null; - try { - schema = sf.newSchema( schemaUrl ); - } - catch ( SAXException e ) { - LOG.debugf( "Unable to create schema for %s: %s", schemaVersion, e.getMessage() ); - } - return schema; - } -} - diff --git a/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/SimpleBindingTest.java b/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/SimpleBindingTest.java index 604a132e30..3daad540b3 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/SimpleBindingTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/metamodel/unified/jaxb/SimpleBindingTest.java @@ -23,28 +23,30 @@ */ package org.hibernate.test.metamodel.unified.jaxb; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + import java.io.InputStream; +import org.hibernate.boot.registry.internal.BootstrapServiceRegistryImpl; +import org.hibernate.metamodel.internal.ClassLoaderAccessImpl; import org.hibernate.metamodel.source.internal.jaxb.JaxbAttributes; import org.hibernate.metamodel.source.internal.jaxb.JaxbBasic; import org.hibernate.metamodel.source.internal.jaxb.JaxbEntity; import org.hibernate.metamodel.source.internal.jaxb.JaxbEntityMappings; +import org.hibernate.testing.junit4.BaseUnitTestCase; import org.hibernate.xml.internal.jaxb.UnifiedMappingBinder; import org.hibernate.xml.spi.Origin; import org.hibernate.xml.spi.SourceType; - -import org.hibernate.testing.junit4.BaseUnitTestCase; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - /** * @author Steve Ebersole */ public class SimpleBindingTest extends BaseUnitTestCase { - private UnifiedMappingBinder binder = new UnifiedMappingBinder( true ); + private UnifiedMappingBinder binder = new UnifiedMappingBinder( true, + new ClassLoaderAccessImpl( null, new BootstrapServiceRegistryImpl() ) ); @Test public void simpleSpecCompliantMappingTest() throws Exception {