HHH-12379 - Add support for persistence_2_2.xsd and orm_2_2.xsd

This commit is contained in:
Steve Ebersole 2018-04-01 12:50:56 -05:00
parent b072981054
commit 3af728b42c
23 changed files with 3137 additions and 226 deletions

View File

@ -20,9 +20,9 @@ import org.hibernate.boot.jaxb.Origin;
import org.hibernate.boot.jaxb.hbm.spi.JaxbHbmHibernateMapping;
import org.hibernate.boot.jaxb.internal.stax.HbmEventReader;
import org.hibernate.boot.jaxb.internal.stax.JpaOrmXmlEventReader;
import org.hibernate.boot.jaxb.internal.stax.LocalSchema;
import org.hibernate.boot.jaxb.spi.Binding;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.xsd.MappingXsdSupport;
import org.hibernate.internal.util.config.ConfigurationException;
import org.jboss.logging.Logger;
@ -38,10 +38,12 @@ public class MappingBinder extends AbstractBinder {
private static final Logger log = Logger.getLogger( MappingBinder.class );
private final XMLEventFactory xmlEventFactory = XMLEventFactory.newInstance();
private final MappingXsdSupport xsdSupport = new MappingXsdSupport();
private JAXBContext hbmJaxbContext;
public MappingBinder(ClassLoaderService classLoaderService) {
super( classLoaderService );
this( classLoaderService, true );
}
public MappingBinder(ClassLoaderService classLoaderService, boolean validateXml) {
@ -58,8 +60,8 @@ public class MappingBinder extends AbstractBinder {
log.debugf( "Performing JAXB binding of hbm.xml document : %s", origin.toString() );
XMLEventReader hbmReader = new HbmEventReader( staxEventReader, xmlEventFactory );
JaxbHbmHibernateMapping hbmBindings = jaxb( hbmReader, LocalSchema.HBM.getSchema(), hbmJaxbContext(), origin );
return new Binding<JaxbHbmHibernateMapping>( hbmBindings, origin );
JaxbHbmHibernateMapping hbmBindings = jaxb( hbmReader, xsdSupport.hbmXsd().getSchema(), hbmJaxbContext(), origin );
return new Binding<>( hbmBindings, origin );
}
else {
// final XMLEventReader reader = new JpaOrmXmlEventReader( staxEventReader );
@ -67,7 +69,7 @@ public class MappingBinder extends AbstractBinder {
try {
final XMLEventReader reader = new JpaOrmXmlEventReader( staxEventReader, xmlEventFactory );
return new Binding<Document>( toDom4jDocument( reader, origin), origin );
return new Binding<>( toDom4jDocument( reader, origin ), origin );
}
catch (JpaOrmXmlEventReader.BadVersionException e) {
throw new UnsupportedOrmXsdVersionException( e.getRequestedVersion(), origin );

View File

@ -19,6 +19,8 @@ import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import javax.xml.stream.util.EventReaderDelegate;
import org.hibernate.boot.xsd.MappingXsdSupport;
/**
* A StAX EventReader for {@code hbm.xml} files to add namespaces in documents
* not containing namespaces.
@ -65,7 +67,7 @@ public class HbmEventReader extends EventReaderDelegate {
if ( "".equals( startElement.getName().getNamespaceURI() ) ) {
// add the default namespace mapping
targetNamespaces.add( xmlEventFactory.createNamespace( LocalSchema.HBM.getNamespaceUri() ) );
targetNamespaces.add( xmlEventFactory.createNamespace( MappingXsdSupport.INSTANCE.hbmXsd().getNamespaceUri() ) );
}
// transfer any namespaces directly, unless it is in the "to map" list in which case
@ -75,7 +77,7 @@ public class HbmEventReader extends EventReaderDelegate {
Namespace namespace = originalNamespaces.next();
if ( NAMESPACE_URIS_TO_MAP.contains( namespace.getNamespaceURI() ) ) {
// this is a namespace "to map" so map it
namespace = xmlEventFactory.createNamespace( namespace.getPrefix(), LocalSchema.HBM.getNamespaceUri() );
namespace = xmlEventFactory.createNamespace( namespace.getPrefix(), MappingXsdSupport.INSTANCE.hbmXsd().getNamespaceUri() );
}
targetNamespaces.add( namespace );
}
@ -84,7 +86,7 @@ public class HbmEventReader extends EventReaderDelegate {
// so that the event we ask it to generate for us has the same location info
xmlEventFactory.setLocation( startElement.getLocation() );
return xmlEventFactory.createStartElement(
new QName( LocalSchema.HBM.getNamespaceUri(), startElement.getName().getLocalPart() ),
new QName( MappingXsdSupport.INSTANCE.hbmXsd().getNamespaceUri(), startElement.getName().getLocalPart() ),
startElement.getAttributes(),
targetNamespaces.iterator()
);

View File

@ -21,6 +21,9 @@ import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import javax.xml.stream.util.EventReaderDelegate;
import org.hibernate.boot.xsd.LocalXsdResolver;
import org.hibernate.boot.xsd.MappingXsdSupport;
/**
* A JPA {@code orm.xml} specific StAX EVentReader to handle a few oddities.
*
@ -44,9 +47,6 @@ public class JpaOrmXmlEventReader extends EventReaderDelegate {
private static final String ROOT_ELEMENT_NAME = "entity-mappings";
private static final String VERSION_ATTRIBUTE_NAME = "version";
private static final String DEFAULT_VERSION = "2.1";
private static final List<String> VALID_VERSIONS = Arrays.asList( "1.0", "2.0", "2.1" );
private final XMLEventFactory xmlEventFactory;
public JpaOrmXmlEventReader(XMLEventReader reader) {
@ -88,14 +88,14 @@ public class JpaOrmXmlEventReader extends EventReaderDelegate {
// so that the event we ask it to generate for us has the same location info
xmlEventFactory.setLocation( startElement.getLocation() );
return xmlEventFactory.createStartElement(
new QName( LocalSchema.ORM.getNamespaceUri(), startElement.getName().getLocalPart() ),
new QName( MappingXsdSupport.INSTANCE.latestJpaDescriptor().getNamespaceUri(), startElement.getName().getLocalPart() ),
newElementAttributeList.iterator(),
newNamespaceList.iterator()
);
}
private List<Attribute> mapAttributes(StartElement startElement) {
final List<Attribute> mappedAttributes = new ArrayList<Attribute>();
final List<Attribute> mappedAttributes = new ArrayList<>();
Iterator<Attribute> existingAttributesIterator = existingXmlAttributesIterator( startElement );
while ( existingAttributesIterator.hasNext() ) {
@ -125,11 +125,11 @@ public class JpaOrmXmlEventReader extends EventReaderDelegate {
if ( VERSION_ATTRIBUTE_NAME.equals( originalAttribute.getName().getLocalPart() ) ) {
final String specifiedVersion = originalAttribute.getValue();
if ( !VALID_VERSIONS.contains( specifiedVersion ) ) {
if ( !LocalXsdResolver.isValidJpaVersion( specifiedVersion ) ) {
throw new BadVersionException( specifiedVersion );
}
return xmlEventFactory.createAttribute( VERSION_ATTRIBUTE_NAME, DEFAULT_VERSION );
return xmlEventFactory.createAttribute( VERSION_ATTRIBUTE_NAME, LocalXsdResolver.latestJpaVerison() );
}
}
@ -156,7 +156,7 @@ public class JpaOrmXmlEventReader extends EventReaderDelegate {
}
if ( mappedNamespaces.isEmpty() ) {
mappedNamespaces.add( xmlEventFactory.createNamespace( LocalSchema.ORM.getNamespaceUri() ) );
mappedNamespaces.add( xmlEventFactory.createNamespace( MappingXsdSupport.INSTANCE.latestJpaDescriptor().getNamespaceUri() ) );
}
return mappedNamespaces;
@ -170,7 +170,7 @@ public class JpaOrmXmlEventReader extends EventReaderDelegate {
private Namespace mapNamespace(Namespace originalNamespace) {
if ( NAMESPACE_URIS_TO_MAP.contains( originalNamespace.getNamespaceURI() ) ) {
// this is a namespace "to map" so map it
return xmlEventFactory.createNamespace( originalNamespace.getPrefix(), LocalSchema.ORM.getNamespaceUri() );
return xmlEventFactory.createNamespace( originalNamespace.getPrefix(), MappingXsdSupport.INSTANCE.latestJpaDescriptor().getNamespaceUri() );
}
return originalNamespace;
@ -183,7 +183,7 @@ public class JpaOrmXmlEventReader extends EventReaderDelegate {
// so that the event we ask it to generate for us has the same location info
xmlEventFactory.setLocation( endElement.getLocation() );
return xmlEventFactory.createEndElement(
new QName( LocalSchema.ORM.getNamespaceUri(), endElement.getName().getLocalPart() ),
new QName( MappingXsdSupport.INSTANCE.latestJpaDescriptor().getNamespaceUri(), endElement.getName().getLocalPart() ),
targetNamespaces.iterator()
);
}

View File

@ -18,7 +18,11 @@ import org.jboss.logging.Logger;
/**
* @author Steve Ebersole
*
* @deprecated No longer used locally. See {@link org.hibernate.boot.xsd.MappingXsdSupport}
* and {@link org.hibernate.boot.xsd.ConfigXsdSupport}
*/
@Deprecated
public enum LocalSchema {
ORM(
"http://www.hibernate.org/xsd/orm/mapping",

View File

@ -1,69 +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.boot.jaxb.internal.stax;
import java.net.URL;
import javax.xml.validation.Schema;
import org.hibernate.boot.jaxb.Origin;
/**
* @author Steve Ebersole
*
* @deprecated since 5.0; no longer used internally.
*/
@Deprecated
public enum SupportedOrmXsdVersion {
ORM_1_0( "org/hibernate/jpa/orm_1_0.xsd" ),
ORM_2_0( "org/hibernate/jpa/orm_2_0.xsd" ),
ORM_2_1( "org/hibernate/jpa/orm_2_1.xsd" ),
ORM_2_1_0( "org/hibernate/xsd/mapping/mapping-2.1.0.xsd" ),
HBM_4_0( "org/hibernate/xsd/mapping/legacy-mapping-4.0.xsd" );
private final String schemaResourceName;
SupportedOrmXsdVersion(String schemaResourceName) {
this.schemaResourceName = schemaResourceName;
}
public static SupportedOrmXsdVersion parse(String name, Origin origin) {
if ( "1.0".equals( name ) ) {
return ORM_1_0;
}
else if ( "2.0".equals( name ) ) {
return ORM_2_0;
}
else if ( "2.1".equals( name ) ) {
return ORM_2_1;
}
else if ( "2.1.0".equals( name ) ) {
return ORM_2_1_0;
}
else if ( "4.0".equals( name ) ) {
return HBM_4_0;
}
throw new UnsupportedOrmXsdVersionException( name, origin );
}
private URL schemaUrl;
public URL getSchemaUrl() {
if ( schemaUrl == null ) {
schemaUrl = LocalSchemaLocator.resolveLocalSchemaUrl( schemaResourceName );
}
return schemaUrl;
}
private Schema schema;
public Schema getSchema() {
if ( schema == null ) {
schema = LocalSchemaLocator.resolveLocalSchema( getSchemaUrl() );
}
return schema;
}
}

View File

@ -1,29 +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.boot.jaxb.internal.stax;
import org.hibernate.HibernateException;
import org.hibernate.boot.jaxb.Origin;
/**
* @author Steve Ebersole
*
* @deprecated Use {@link org.hibernate.boot.UnsupportedOrmXsdVersionException} instead
*/
@Deprecated
public class UnsupportedOrmXsdVersionException extends HibernateException {
public UnsupportedOrmXsdVersionException(String requestedVersion, Origin origin) {
super(
String.format(
"Encountered unsupported orm.xml xsd version [%s] in mapping document [type=%s, name=%s]",
requestedVersion,
origin.getType(),
origin.getName()
)
);
}
}

View File

@ -0,0 +1,83 @@
/*
* 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.boot.xsd;
import org.jboss.logging.Logger;
/**
* Support for XSD handling related to Hibernate's `cfg.xml` and
* JPA's `persistence.xml`.
*
* @author Steve Ebersole
*/
@SuppressWarnings("unused")
public class ConfigXsdSupport {
private static final Logger log = Logger.getLogger( ConfigXsdSupport.class );
/**
* Singleton access
*/
public static final ConfigXsdSupport INSTANCE = new ConfigXsdSupport();
private final XsdDescriptor jpa10 = LocalXsdResolver.buildXsdDescriptor(
"org/hibernate/jpa/persistence_1_0.xsd",
"1.0",
"http://java.sun.com/xml/ns/persistence"
);
private final XsdDescriptor jpa20 = LocalXsdResolver.buildXsdDescriptor(
"org/hibernate/jpa/persistence_2_0.xsd",
"2.0" ,
"http://java.sun.com/xml/ns/persistence"
);
private final XsdDescriptor jpa21 = LocalXsdResolver.buildXsdDescriptor(
"org/hibernate/jpa/persistence_2_1.xsd",
"2.1",
"http://xmlns.jcp.org/xml/ns/persistence"
);
private final XsdDescriptor jpa22 = LocalXsdResolver.buildXsdDescriptor(
"org/hibernate/jpa/persistence_2_2.xsd",
"2.2" ,
"http://xmlns.jcp.org/xml/ns/persistence"
);
private final XsdDescriptor cfgXml = LocalXsdResolver.buildXsdDescriptor(
"org/hibernate/xsd/cfg/legacy-configuration-4.0.xsd",
"4.0" ,
"http://www.hibernate.org/xsd/orm/cfg"
);
public XsdDescriptor latestJpaDescriptor() {
return jpa22;
}
public XsdDescriptor jpaXsd(String version) {
switch ( version ) {
case "1.0": {
return jpa10;
}
case "2.0": {
return jpa20;
}
case "2.1": {
return jpa21;
}
case "2.2": {
return jpa22;
}
default: {
throw new IllegalArgumentException( "Unrecognized JPA persistence.xml XSD version : `" + version + "`" );
}
}
}
public XsdDescriptor cfgXsd() {
return cfgXml;
}
}

View File

@ -0,0 +1,113 @@
/*
* 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.boot.xsd;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.hibernate.internal.util.xml.XsdException;
import org.jboss.logging.Logger;
import org.xml.sax.SAXException;
/**
* When Hibernate loads an XSD we fully expect that to be resolved from our
* jar file via ClassLoader resource look-up. This class simplifies
* the steps needed to achieve those goals explicitly using its own
* ClassLoader for the look-ups.
*
* @author Steve Ebersole
*/
@SuppressWarnings("WeakerAccess")
public class LocalXsdResolver {
private static final Logger log = Logger.getLogger( LocalXsdResolver.class );
private static final List<String> VALID_JPA_VERSIONS = Arrays.asList( "1.0", "2.0", "2.1", "2.2" );
public static String latestJpaVerison() {
return "2.2";
}
public static boolean isValidJpaVersion(String version) {
return VALID_JPA_VERSIONS.contains( version );
}
public static URL resolveLocalXsdUrl(String resourceName) {
// first we try name as a URL
try {
return new URL( resourceName );
}
catch (Exception ignore) {
}
try {
final URL url = LocalXsdResolver.class.getClassLoader().getResource( resourceName );
if ( url != null ) {
return url;
}
}
catch (Exception ignore) {
}
if ( resourceName.startsWith( "/" ) ) {
resourceName = resourceName.substring( 1 );
try {
final URL url = LocalXsdResolver.class.getClassLoader().getResource( resourceName );
if ( url != null ) {
return url;
}
}
catch (Exception ignore) {
}
}
return null;
}
public static Schema resolveLocalXsdSchema(String schemaResourceName) {
final URL url = resolveLocalXsdUrl( schemaResourceName );
if ( url == null ) {
throw new XsdException( "Unable to locate schema [" + schemaResourceName + "] via classpath", schemaResourceName );
}
try {
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 );
}
catch ( SAXException | IOException e ) {
throw new XsdException( "Unable to load schema [" + schemaResourceName + "]", e, schemaResourceName );
}
finally {
try {
schemaStream.close();
}
catch ( IOException e ) {
log.debugf( "Problem closing schema stream [%s]", e.toString() );
}
}
}
catch ( IOException e ) {
throw new XsdException( "Stream error handling schema url [" + url.toExternalForm() + "]", schemaResourceName );
}
}
public static XsdDescriptor buildXsdDescriptor(String resourceName, String version, String namespaceUri) {
return new XsdDescriptor( resourceName, resolveLocalXsdSchema( resourceName ), version, namespaceUri );
}
}

View File

@ -0,0 +1,81 @@
/*
* 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.boot.xsd;
/**
* Support for XSD handling related to Hibernate's `hbm.xml` and
* JPA's `orm.xml`.
*
* @author Steve Ebersole
*/
@SuppressWarnings("unused")
public class MappingXsdSupport {
/**
* Singleton access
*/
public static final MappingXsdSupport INSTANCE = new MappingXsdSupport();
private final XsdDescriptor jpa10 = LocalXsdResolver.buildXsdDescriptor(
"org/hibernate/jpa/orm_1_0.xsd",
"1.0",
"http://java.sun.com/xml/ns/persistence/orm"
);
private final XsdDescriptor jpa20 = LocalXsdResolver.buildXsdDescriptor(
"org/hibernate/jpa/orm_2_0.xsd",
"2.0",
"http://java.sun.com/xml/ns/persistence/orm"
);
private final XsdDescriptor jpa21 = LocalXsdResolver.buildXsdDescriptor(
"org/hibernate/jpa/orm_2_1.xsd",
"2.1",
"http://xmlns.jcp.org/xml/ns/persistence"
);
private final XsdDescriptor jpa22 = LocalXsdResolver.buildXsdDescriptor(
"org/hibernate/jpa/orm_2_2.xsd",
"2.2",
"http://xmlns.jcp.org/xml/ns/persistence"
);
private final XsdDescriptor hbmXml = LocalXsdResolver.buildXsdDescriptor(
"org/hibernate/xsd/mapping/legacy-mapping-4.0.xsd",
"4.0",
"http://www.hibernate.org/xsd/orm/hbm"
);
public XsdDescriptor latestJpaDescriptor() {
return jpa22;
}
public XsdDescriptor jpaXsd(String version) {
switch ( version ) {
case "1.0": {
return jpa10;
}
case "2.0": {
return jpa20;
}
case "2.1": {
return jpa21;
}
case "2.2": {
return jpa22;
}
default: {
throw new IllegalArgumentException( "Unrecognized JPA orm.xml XSD version : `" + version + "`" );
}
}
}
public XsdDescriptor hbmXsd() {
return hbmXml;
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.boot.xsd;
import javax.xml.validation.Schema;
/**
* Representation of a locally resolved XSD
*
* @author Steve Ebersole
*/
public class XsdDescriptor {
private final String localResourceName;
private final String namespaceUri;
private final String version;
private final Schema schema;
public XsdDescriptor(String localResourceName, Schema schema, String version, String namespaceUri) {
this.localResourceName = localResourceName;
this.schema = schema;
this.version = version;
this.namespaceUri = namespaceUri;
}
public String getLocalResourceName() {
return localResourceName;
}
public String getNamespaceUri() {
return namespaceUri;
}
public String getVersion() {
return version;
}
public Schema getSchema() {
return schema;
}
}

View File

@ -0,0 +1,12 @@
/*
* 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
*/
/**
* Support for XSD handling, specifically for ORM mappings (Hibernate's `hbm.xml` and
* JPA's `orm.xml`) and config files (Hibernate's `cfg.xml` and JPA's `persistence.xml`)
*/
package org.hibernate.boot.xsd;

View File

@ -18,23 +18,19 @@ import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import javax.persistence.PersistenceException;
import javax.persistence.spi.PersistenceUnitTransactionType;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.hibernate.boot.archive.internal.ArchiveHelper;
import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.xsd.ConfigXsdSupport;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.internal.EntityManagerMessageLogger;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.xml.XsdException;
import org.hibernate.jpa.internal.util.ConfigurationHelper;
import org.w3c.dom.Document;
@ -204,8 +200,7 @@ public class PersistenceXmlParser {
public static Map<String, ParsedPersistenceXmlDescriptor> parse(
URL persistenceXmlUrl,
PersistenceUnitTransactionType transactionType,
Map integration
) {
Map integration) {
PersistenceXmlParser parser = new PersistenceXmlParser(
ClassLoaderServiceImpl.fromConfigSettings( integration ),
transactionType
@ -215,6 +210,7 @@ public class PersistenceXmlParser {
return parser.persistenceUnits;
}
private final ConfigXsdSupport xsdSupport = new ConfigXsdSupport();
private final ClassLoaderService classLoaderService;
private final PersistenceUnitTransactionType defaultTransactionType;
private final Map<String, ParsedPersistenceXmlDescriptor> persistenceUnits;
@ -435,8 +431,7 @@ public class PersistenceXmlParser {
URLConnection conn = xmlUrl.openConnection();
conn.setUseCaches( false ); //avoid JAR locking on Windows and Tomcat
try {
InputStream inputStream = conn.getInputStream();
try {
try (InputStream inputStream = conn.getInputStream()) {
final InputSource inputSource = new InputSource( inputStream );
try {
DocumentBuilder documentBuilder = documentBuilderFactory().newDocumentBuilder();
@ -445,22 +440,15 @@ public class PersistenceXmlParser {
validate( document );
return document;
}
catch (SAXException e) {
throw new PersistenceException( "Unexpected error parsing [" + resourceName + "]", e );
}
catch (IOException e) {
catch (SAXException | IOException e) {
throw new PersistenceException( "Unexpected error parsing [" + resourceName + "]", e );
}
}
catch (ParserConfigurationException e) {
throw new PersistenceException( "Unable to generate javax.xml.parsers.DocumentBuilder instance", e );
}
}
finally {
try {
inputStream.close();
}
catch (Exception ignored) {
throw new PersistenceException(
"Unable to generate javax.xml.parsers.DocumentBuilder instance",
e
);
}
}
}
@ -476,22 +464,10 @@ public class PersistenceXmlParser {
private void validate(Document document) {
// todo : add ability to disable validation...
final Validator validator;
final String version = document.getDocumentElement().getAttribute( "version" );
if ( "2.1".equals( version ) ) {
validator = v21Schema().newValidator();
}
else if ( "2.0".equals( version ) ) {
validator = v2Schema().newValidator();
}
else if ( "1.0".equals( version ) ) {
validator = v1Schema().newValidator();
}
else {
throw new PersistenceException( "Unrecognized persistence.xml version [" + version + "]" );
}
final Validator validator = xsdSupport.jpaXsd( version ).getSchema().newValidator();
List<SAXException> errors = new ArrayList<SAXException>();
List<SAXException> errors = new ArrayList<>();
validator.setErrorHandler( new ErrorHandlerImpl( errors ) );
try {
validator.validate( new DOMSource( document ) );
@ -528,68 +504,6 @@ public class PersistenceXmlParser {
return documentBuilderFactory;
}
private Schema v21Schema;
private Schema v21Schema() {
if ( v21Schema == null ) {
v21Schema = resolveLocalSchema( "org/hibernate/jpa/persistence_2_1.xsd" );
}
return v21Schema;
}
private Schema v2Schema;
private Schema v2Schema() {
if ( v2Schema == null ) {
v2Schema = resolveLocalSchema( "org/hibernate/jpa/persistence_2_0.xsd" );
}
return v2Schema;
}
private Schema v1Schema;
private Schema v1Schema() {
if ( v1Schema == null ) {
v1Schema = resolveLocalSchema( "org/hibernate/jpa/persistence_1_0.xsd" );
}
return v1Schema;
}
private Schema resolveLocalSchema(String schemaName) {
// These XSD resources should be available on the Hibernate ClassLoader
final URL url = classLoaderService.locateResource( schemaName );
if ( url == null ) {
throw new XsdException( "Unable to locate schema [" + schemaName + "] via classpath", schemaName );
}
try {
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 );
}
catch ( SAXException e ) {
throw new XsdException( "Unable to load schema [" + schemaName + "]", e, schemaName );
}
catch ( IOException e ) {
throw new XsdException( "Unable to load schema [" + schemaName + "]", e, schemaName );
}
finally {
try {
schemaStream.close();
}
catch ( IOException e ) {
LOG.debugf( "Problem closing schema stream [%s]", e.toString() );
}
}
}
catch ( IOException e ) {
throw new XsdException( "Stream error handling schema url [" + url.toExternalForm() + "]", schemaName );
}
}
public static class ErrorHandlerImpl implements ErrorHandler {
private List<SAXException> errors;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,341 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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
-->
<xsd:schema targetNamespace="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:persistence="http://xmlns.jcp.org/xml/ns/persistence"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
version="2.2">
<xsd:annotation>
<xsd:documentation>
@(#)persistence_2_1.xsd 2.1 February 8, 2013
</xsd:documentation>
</xsd:annotation>
<xsd:annotation>
<xsd:documentation><![CDATA[
This is the XML Schema for the persistence configuration file.
The file must be named "META-INF/persistence.xml" in the
persistence archive.
Persistence configuration files must indicate
the persistence schema by using the persistence namespace:
http://xmlns.jcp.org/xml/ns/persistence
and indicate the version of the schema by
using the version element as shown below:
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
...
</persistence>
]]></xsd:documentation>
</xsd:annotation>
<xsd:simpleType name="versionType">
<xsd:restriction base="xsd:token">
<xsd:pattern value="[0-9]+(\.[0-9]+)*"/>
</xsd:restriction>
</xsd:simpleType>
<!-- **************************************************** -->
<xsd:element name="persistence">
<xsd:complexType>
<xsd:sequence>
<!-- **************************************************** -->
<xsd:element name="persistence-unit"
minOccurs="1" maxOccurs="unbounded">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Configuration of a persistence unit.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<!-- **************************************************** -->
<xsd:element name="description" type="xsd:string"
minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Description of this persistence unit.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- **************************************************** -->
<xsd:element name="provider" type="xsd:string"
minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Provider class that supplies EntityManagers for this
persistence unit.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- **************************************************** -->
<xsd:element name="jta-data-source" type="xsd:string"
minOccurs="0">
<xsd:annotation>
<xsd:documentation>
The container-specific name of the JTA datasource to use.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- **************************************************** -->
<xsd:element name="non-jta-data-source" type="xsd:string"
minOccurs="0">
<xsd:annotation>
<xsd:documentation>
The container-specific name of a non-JTA datasource to use.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- **************************************************** -->
<xsd:element name="mapping-file" type="xsd:string"
minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>
File containing mapping information. Loaded as a resource
by the persistence provider.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- **************************************************** -->
<xsd:element name="jar-file" type="xsd:string"
minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>
Jar file that is to be scanned for managed classes.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- **************************************************** -->
<xsd:element name="class" type="xsd:string"
minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>
Managed class to be included in the persistence unit and
to scan for annotations. It should be annotated
with either @Entity, @Embeddable or @MappedSuperclass.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- **************************************************** -->
<xsd:element name="exclude-unlisted-classes" type="xsd:boolean"
default="true" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
When set to true then only listed classes and jars will
be scanned for persistent classes, otherwise the
enclosing jar or directory will also be scanned.
Not applicable to Java SE persistence units.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- **************************************************** -->
<xsd:element name="shared-cache-mode"
type="persistence:persistence-unit-caching-type"
minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Defines whether caching is enabled for the
persistence unit if caching is supported by the
persistence provider. When set to ALL, all entities
will be cached. When set to NONE, no entities will
be cached. When set to ENABLE_SELECTIVE, only entities
specified as cacheable will be cached. When set to
DISABLE_SELECTIVE, entities specified as not cacheable
will not be cached. When not specified or when set to
UNSPECIFIED, provider defaults may apply.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- **************************************************** -->
<xsd:element name="validation-mode"
type="persistence:persistence-unit-validation-mode-type"
minOccurs="0">
<xsd:annotation>
<xsd:documentation>
The validation mode to be used for the persistence unit.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- **************************************************** -->
<xsd:element name="properties" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
A list of standard and vendor-specific properties
and hints.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence>
<xsd:element name="property"
minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>
A name-value pair.
</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:attribute name="name" type="xsd:string"
use="required"/>
<xsd:attribute name="value" type="xsd:string"
use="required"/>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<!-- **************************************************** -->
<xsd:attribute name="name" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation>
Name used in code to reference this persistence unit.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<!-- **************************************************** -->
<xsd:attribute name="transaction-type"
type="persistence:persistence-unit-transaction-type">
<xsd:annotation>
<xsd:documentation>
Type of transactions used by EntityManagers from this
persistence unit.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="version" type="persistence:versionType"
fixed="2.1" use="required"/>
</xsd:complexType>
</xsd:element>
<!-- **************************************************** -->
<xsd:simpleType name="persistence-unit-transaction-type">
<xsd:annotation>
<xsd:documentation>
public enum PersistenceUnitTransactionType {JTA, RESOURCE_LOCAL};
</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:token">
<xsd:enumeration value="JTA"/>
<xsd:enumeration value="RESOURCE_LOCAL"/>
</xsd:restriction>
</xsd:simpleType>
<!-- **************************************************** -->
<xsd:simpleType name="persistence-unit-caching-type">
<xsd:annotation>
<xsd:documentation>
public enum SharedCacheMode { ALL, NONE, ENABLE_SELECTIVE, DISABLE_SELECTIVE, UNSPECIFIED};
</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:token">
<xsd:enumeration value="ALL"/>
<xsd:enumeration value="NONE"/>
<xsd:enumeration value="ENABLE_SELECTIVE"/>
<xsd:enumeration value="DISABLE_SELECTIVE"/>
<xsd:enumeration value="UNSPECIFIED"/>
</xsd:restriction>
</xsd:simpleType>
<!-- **************************************************** -->
<xsd:simpleType name="persistence-unit-validation-mode-type">
<xsd:annotation>
<xsd:documentation>
public enum ValidationMode { AUTO, CALLBACK, NONE};
</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:token">
<xsd:enumeration value="AUTO"/>
<xsd:enumeration value="CALLBACK"/>
<xsd:enumeration value="NONE"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>

View File

@ -17,7 +17,7 @@ import org.hibernate.jpa.AvailableSettings;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.hibernate.jpa.boot.spi.Bootstrap;
import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder;
import org.hibernate.jpa.test.jee.OrmVersionTest;
import org.hibernate.test.jpa.xml.versions.JpaXsdVersionsTest;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.junit.After;
@ -49,7 +49,7 @@ public class ValidatorFactory2PhaseInjectionTest extends BaseUnitTestCase {
@Test
public void testInjectionAvailabilityFromEmf() {
EntityManagerFactoryBuilder emfb = Bootstrap.getEntityManagerFactoryBuilder(
new OrmVersionTest.PersistenceUnitInfoImpl( "my-test" ) {
new JpaXsdVersionsTest.PersistenceUnitInfoImpl( "my-test" ) {
@Override
public URL getPersistenceUnitRootUrl() {
// just get any known url...

View File

@ -11,7 +11,7 @@ import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.jpa.test.jee.OrmVersionTest;
import org.hibernate.test.jpa.xml.versions.JpaXsdVersionsTest;
import org.hibernate.jpa.HibernatePersistenceProvider;
import org.junit.Test;
@ -26,7 +26,7 @@ public class NewBootProcessTest {
HibernatePersistenceProvider persistenceProvider = new HibernatePersistenceProvider();
final EntityManagerFactory emf = persistenceProvider.createContainerEntityManagerFactory(
new OrmVersionTest.PersistenceUnitInfoImpl( "my-test" ) {
new JpaXsdVersionsTest.PersistenceUnitInfoImpl( "my-test" ) {
@Override
public URL getPersistenceUnitRootUrl() {
// just get any known url...

View File

@ -1,10 +1,10 @@
/*
* 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>.
* 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.jpa.test.jee;
package org.hibernate.test.jpa.xml.versions;
import java.net.URL;
import java.util.ArrayList;
@ -34,11 +34,11 @@ import org.junit.Test;
*
* @author Steve Ebersole
*/
public class OrmVersionTest {
public class JpaXsdVersionsTest {
@Test
public void testOrm1() {
PersistenceUnitInfoImpl pui = new PersistenceUnitInfoImpl( "orm1-test", "1.0" )
.addMappingFileName( "org/hibernate/jpa/test/jee/valid-orm-1.xml" );
.addMappingFileName( "org/hibernate/test/jpa/xml/versions/valid-orm-1_0.xml" );
HibernatePersistenceProvider hp = new HibernatePersistenceProvider();
EntityManagerFactory emf = hp.createContainerEntityManagerFactory( pui, Collections.EMPTY_MAP );
try {
@ -50,9 +50,37 @@ public class OrmVersionTest {
}
@Test
public void testOrm2() {
public void testOrm20() {
PersistenceUnitInfoImpl pui = new PersistenceUnitInfoImpl( "orm2-test", "2.0" )
.addMappingFileName( "org/hibernate/jpa/test/jee/valid-orm-2.xml" );
.addMappingFileName( "org/hibernate/test/jpa/xml/versions/valid-orm-2_0.xml" );
HibernatePersistenceProvider hp = new HibernatePersistenceProvider();
EntityManagerFactory emf = hp.createContainerEntityManagerFactory( pui, Collections.EMPTY_MAP );
try {
emf.getMetamodel().entity( Lighter.class ); // exception if not entity
}
finally {
emf.close();
}
}
@Test
public void testOrm21() {
PersistenceUnitInfoImpl pui = new PersistenceUnitInfoImpl( "orm2-test", "2.1" )
.addMappingFileName( "org/hibernate/test/jpa/xml/versions/valid-orm-2_1.xml" );
HibernatePersistenceProvider hp = new HibernatePersistenceProvider();
EntityManagerFactory emf = hp.createContainerEntityManagerFactory( pui, Collections.EMPTY_MAP );
try {
emf.getMetamodel().entity( Lighter.class ); // exception if not entity
}
finally {
emf.close();
}
}
@Test
public void testOrm22() {
PersistenceUnitInfoImpl pui = new PersistenceUnitInfoImpl( "orm2-test", "2.2")
.addMappingFileName( "org/hibernate/test/jpa/xml/versions/valid-orm-2_2.xml" );
HibernatePersistenceProvider hp = new HibernatePersistenceProvider();
EntityManagerFactory emf = hp.createContainerEntityManagerFactory( pui, Collections.EMPTY_MAP );
try {
@ -66,7 +94,7 @@ public class OrmVersionTest {
@Test
public void testInvalidOrm1() {
PersistenceUnitInfoImpl pui = new PersistenceUnitInfoImpl( "invalid-orm1-test", "1.0" )
.addMappingFileName( "org/hibernate/jpa/test/jee/invalid-orm-1.xml" );
.addMappingFileName( "org/hibernate/test/jpa/xml/versions/invalid-orm-1_0.xml" );
HibernatePersistenceProvider hp = new HibernatePersistenceProvider();
EntityManagerFactory emf = null;
try {
@ -94,7 +122,7 @@ public class OrmVersionTest {
private final String persistenceSchemaVersion;
public PersistenceUnitInfoImpl(String name) {
this( name, "2.0" );
this( name, "2.2" );
}
public PersistenceUnitInfoImpl(String name, String persistenceSchemaVersion) {

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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
-->
<entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm http://xmlns.jcp.org/xml/ns/persistence/orm_2_1.xsd"
version="2.1"
>
<persistence-unit-metadata>
<persistence-unit-defaults>
<delimited-identifiers/>
<entity-listeners>
<entity-listener class="org.hibernate.jpa.test.pack.defaultpar.IncrementListener">
<pre-persist method-name="increment"/>
</entity-listener>
</entity-listeners>
</persistence-unit-defaults>
</persistence-unit-metadata>
<package>org.hibernate.jpa.test.pack.defaultpar</package>
<entity class="Lighter" access="FIELD" metadata-complete="true">
<attributes>
<id name="name">
<column name="fld_id"/>
</id>
<basic name="power"></basic>
</attributes>
</entity>
<entity class="ApplicationServer">
<entity-listeners>
<entity-listener class="OtherIncrementListener">
<pre-persist method-name="increment"/>
</entity-listener>
</entity-listeners>
</entity>
</entity-mappings>

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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
-->
<!--<entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"-->
<!--xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"-->
<!--xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm http://xmlns.jcp.org/xml/ns/persistence/orm_2_2.xsd"-->
<!--version="2.2"-->
<!--&gt;-->
<entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.2"
>
<persistence-unit-metadata>
<persistence-unit-defaults>
<delimited-identifiers/>
<entity-listeners>
<entity-listener class="org.hibernate.jpa.test.pack.defaultpar.IncrementListener">
<pre-persist method-name="increment"/>
</entity-listener>
</entity-listeners>
</persistence-unit-defaults>
</persistence-unit-metadata>
<package>org.hibernate.jpa.test.pack.defaultpar</package>
<entity class="Lighter" access="FIELD" metadata-complete="true">
<attributes>
<id name="name">
<column name="fld_id"/>
</id>
<basic name="power"></basic>
</attributes>
</entity>
<entity class="ApplicationServer">
<entity-listeners>
<entity-listener class="OtherIncrementListener">
<pre-persist method-name="increment"/>
</entity-listener>
</entity-listeners>
</entity>
</entity-mappings>