HHH-17377 - Migrate to JPA 3.2

https://hibernate.atlassian.net/browse/HHH-17377

JPA 3.2 B02
This commit is contained in:
Steve Ebersole 2023-11-07 16:52:47 -06:00
parent ad26e73c44
commit ffd5e26164
12 changed files with 340 additions and 318 deletions

View File

@ -0,0 +1,31 @@
/*
* 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.cfg.internal;
import org.hibernate.internal.util.StringHelper;
import jakarta.persistence.SharedCacheMode;
import jakarta.persistence.spi.PersistenceUnitTransactionType;
/**
* @author Steve Ebersole
*/
public class SharedCacheModeMarshalling {
public static SharedCacheMode fromXml(String name) {
if ( StringHelper.isEmpty( name ) ) {
return SharedCacheMode.UNSPECIFIED;
}
return SharedCacheMode.valueOf( name );
}
public static String toXml(SharedCacheMode sharedCacheMode) {
if ( sharedCacheMode == null ) {
return null;
}
return sharedCacheMode.name();
}
}

View File

@ -0,0 +1,31 @@
/*
* 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.cfg.internal;
import org.hibernate.internal.util.StringHelper;
import jakarta.persistence.AccessType;
import jakarta.persistence.spi.PersistenceUnitTransactionType;
/**
* @author Steve Ebersole
*/
public class TransactionTypeMarshalling {
public static PersistenceUnitTransactionType fromXml(String name) {
if ( StringHelper.isEmpty( name ) ) {
return PersistenceUnitTransactionType.RESOURCE_LOCAL;
}
return PersistenceUnitTransactionType.valueOf( name );
}
public static String toXml(PersistenceUnitTransactionType transactionType) {
if ( transactionType == null ) {
return null;
}
return transactionType.name();
}
}

View File

@ -0,0 +1,31 @@
/*
* 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.cfg.internal;
import org.hibernate.internal.util.StringHelper;
import jakarta.persistence.SharedCacheMode;
import jakarta.persistence.ValidationMode;
/**
* @author Steve Ebersole
*/
public class ValidationModeMarshalling {
public static ValidationMode fromXml(String name) {
if ( StringHelper.isEmpty( name ) ) {
return ValidationMode.AUTO;
}
return ValidationMode.valueOf( name );
}
public static String toXml(ValidationMode validationMode) {
if ( validationMode == null ) {
return null;
}
return validationMode.name();
}
}

View File

@ -146,7 +146,7 @@ public abstract class AbstractEventReader extends EventReaderDelegate {
}
private Namespace mapNamespace(Namespace originalNamespace) {
if ( XsdHelper.shouldBeMappedToLatestJpaDescriptor( originalNamespace.getNamespaceURI() ) ) {
if ( shouldBeMappedToLatestJpaDescriptor( originalNamespace.getNamespaceURI() ) ) {
// this is a namespace "to map" so map it
return xmlEventFactory.createNamespace( originalNamespace.getPrefix(), xsdDescriptor.getNamespaceUri() );
}
@ -154,6 +154,8 @@ public abstract class AbstractEventReader extends EventReaderDelegate {
return originalNamespace;
}
protected abstract boolean shouldBeMappedToLatestJpaDescriptor(String uri);
private XMLEvent wrap(EndElement endElement) {
final List<Namespace> targetNamespaces = mapNamespaces( existingXmlNamespacesIterator( endElement ) );

View File

@ -20,9 +20,14 @@ public class ConfigurationEventReader extends AbstractEventReader {
public ConfigurationEventReader(XMLEventReader reader, XMLEventFactory xmlEventFactory) {
super(
ROOT_ELEMENT_NAME,
ConfigXsdSupport.getJPA32(),
ConfigXsdSupport.configurationXsd(),
reader,
xmlEventFactory
);
}
@Override
protected boolean shouldBeMappedToLatestJpaDescriptor(String uri) {
return !ConfigXsdSupport.configurationXsd().getNamespaceUri().equals( uri );
}
}

View File

@ -24,4 +24,8 @@ public class MappingEventReader extends AbstractEventReader {
super( ROOT_ELEMENT_NAME, MappingXsdSupport.latestDescriptor(), reader, xmlEventFactory );
}
@Override
protected boolean shouldBeMappedToLatestJpaDescriptor(String uri) {
return !MappingXsdSupport.latestDescriptor().getNamespaceUri().equals( uri );
}
}

View File

@ -41,8 +41,12 @@ public class ConfigXsdSupport {
}
public static boolean shouldBeMappedToLatestJpaDescriptor(String uri) {
// JPA 1.0 and 2.0 share the same namespace URI
return getJPA10().getNamespaceUri().matches( uri );
// Any namespace prior to move to Jakarta (3.0) needs to be remapped
// NOTE:
// - JPA 1.0 and 2.0 share the same namespace URI
// - JPA 2.1 and 2.2 share the same namespace URI
return !configurationXsd().getNamespaceUri().equals( uri );
}
public XsdDescriptor jpaXsd(String version) {

View File

@ -19,6 +19,7 @@ public class XsdHelper {
public static boolean shouldBeMappedToLatestJpaDescriptor(String uri) {
// JPA 1.0 and 2.0 share the same namespace URI
// JPA 2.1 and 2.2 share the same namespace URI
return MappingXsdSupport.jpa10.getNamespaceUri().equals( uri );
}
}

View File

@ -9,17 +9,17 @@ package org.hibernate.jpa.boot.internal;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import org.hibernate.boot.archive.internal.ArchiveHelper;
import org.hibernate.bytecode.enhance.spi.EnhancementContext;
import org.hibernate.bytecode.spi.ClassTransformer;
import jakarta.persistence.SharedCacheMode;
import jakarta.persistence.ValidationMode;
import jakarta.persistence.spi.PersistenceUnitTransactionType;
import org.hibernate.bytecode.enhance.spi.EnhancementContext;
import org.hibernate.bytecode.spi.ClassTransformer;
/**
* Describes the information gleaned from a {@code <persistence-unit/>} element in a {@code persistence.xml} file
* whether parsed directly by Hibernate or passed to us by an EE container as a
@ -130,8 +130,12 @@ public class ParsedPersistenceXmlDescriptor implements org.hibernate.jpa.boot.sp
return validationMode;
}
public void setValidationMode(ValidationMode validationMode) {
this.validationMode = validationMode;
}
public void setValidationMode(String validationMode) {
this.validationMode = ValidationMode.valueOf( validationMode );
setValidationMode( ValidationMode.valueOf( validationMode ) );
}
@Override
@ -139,8 +143,12 @@ public class ParsedPersistenceXmlDescriptor implements org.hibernate.jpa.boot.sp
return sharedCacheMode;
}
public void setSharedCacheMode(SharedCacheMode sharedCacheMode) {
this.sharedCacheMode = sharedCacheMode;
}
public void setSharedCacheMode(String sharedCacheMode) {
this.sharedCacheMode = SharedCacheMode.valueOf( sharedCacheMode );
setSharedCacheMode( SharedCacheMode.valueOf( sharedCacheMode ) );
}
@Override
@ -178,6 +186,12 @@ public class ParsedPersistenceXmlDescriptor implements org.hibernate.jpa.boot.sp
jarFileUrls.add( jarFileUrl );
}
public void addJarFileUrls(List<String> jarFiles) {
jarFiles.forEach( (jarFile) -> {
addJarFileUrl( ArchiveHelper.getURLFromPath( jarFile ) );
} );
}
@Override
public ClassLoader getClassLoader() {
return null;

View File

@ -16,32 +16,26 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.spi.PersistenceUnitTransactionType;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.dom.DOMSource;
import javax.xml.validation.Validator;
import javax.xml.transform.stream.StreamSource;
import org.hibernate.boot.archive.internal.ArchiveHelper;
import org.hibernate.boot.jaxb.Origin;
import org.hibernate.boot.jaxb.SourceType;
import org.hibernate.boot.jaxb.configuration.spi.JaxbPersistenceImpl;
import org.hibernate.boot.jaxb.configuration.spi.JaxbPersistenceImpl.JaxbPersistenceUnitImpl.JaxbPropertiesImpl;
import org.hibernate.boot.jaxb.configuration.spi.JaxbPersistenceImpl.JaxbPersistenceUnitImpl.JaxbPropertiesImpl.JaxbPropertyImpl;
import org.hibernate.boot.jaxb.internal.ConfigurationBinder;
import org.hibernate.boot.jaxb.spi.Binding;
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.log.DeprecationLogger;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.jpa.internal.util.ConfigurationHelper;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.spi.PersistenceUnitTransactionType;
import static org.hibernate.internal.HEMLogging.messageLogger;
@ -61,7 +55,8 @@ public class PersistenceXmlParser {
*
* @return List of descriptors for all discovered persistence-units.
*/
public static List<ParsedPersistenceXmlDescriptor> locatePersistenceUnits(Map integration) {
@SuppressWarnings({ "removal", "deprecation" })
public static List<ParsedPersistenceXmlDescriptor> locatePersistenceUnits(Map<?,?> integration) {
final PersistenceXmlParser parser = new PersistenceXmlParser(
ClassLoaderServiceImpl.fromConfigSettings( integration ),
PersistenceUnitTransactionType.RESOURCE_LOCAL
@ -91,7 +86,8 @@ public class PersistenceXmlParser {
*
* @return The single persistence-unit descriptor
*/
public static ParsedPersistenceXmlDescriptor locateIndividualPersistenceUnit(URL persistenceXmlUrl, Map integration) {
@SuppressWarnings("removal")
public static ParsedPersistenceXmlDescriptor locateIndividualPersistenceUnit(URL persistenceXmlUrl, Map<?,?> integration) {
return locateIndividualPersistenceUnit( persistenceXmlUrl, PersistenceUnitTransactionType.RESOURCE_LOCAL, integration );
}
@ -105,10 +101,11 @@ public class PersistenceXmlParser {
*
* @return The single persistence-unit descriptor
*/
@SuppressWarnings({ "removal", "deprecation" })
public static ParsedPersistenceXmlDescriptor locateIndividualPersistenceUnit(
URL persistenceXmlUrl,
PersistenceUnitTransactionType transactionType,
Map integration) {
Map<?,?> integration) {
final PersistenceXmlParser parser = new PersistenceXmlParser(
ClassLoaderServiceImpl.fromConfigSettings( integration ),
transactionType
@ -142,7 +139,8 @@ public class PersistenceXmlParser {
*
* @return The matching persistence-unit descriptor
*/
public static ParsedPersistenceXmlDescriptor locateNamedPersistenceUnit(URL persistenceXmlUrl, String name, Map integration) {
@SuppressWarnings("removal")
public static ParsedPersistenceXmlDescriptor locateNamedPersistenceUnit(URL persistenceXmlUrl, String name, Map<?,?> integration) {
return locateNamedPersistenceUnit( persistenceXmlUrl, name, PersistenceUnitTransactionType.RESOURCE_LOCAL, integration );
}
@ -156,11 +154,12 @@ public class PersistenceXmlParser {
*
* @return The matching persistence-unit descriptor
*/
@SuppressWarnings({ "removal", "deprecation" })
public static ParsedPersistenceXmlDescriptor locateNamedPersistenceUnit(
URL persistenceXmlUrl,
String name,
PersistenceUnitTransactionType transactionType,
Map integration) {
Map<?,?> integration) {
assert StringHelper.isNotEmpty( name );
final PersistenceXmlParser parser = new PersistenceXmlParser(
@ -179,6 +178,7 @@ public class PersistenceXmlParser {
* <p>
* Parses a specific persistence.xml file...
*/
@SuppressWarnings("removal")
public static Map<String, ParsedPersistenceXmlDescriptor> parse(
URL persistenceXmlUrl,
PersistenceUnitTransactionType transactionType) {
@ -195,10 +195,11 @@ public class PersistenceXmlParser {
*
* @return Map of persistence-unit descriptors keyed by the PU name
*/
@SuppressWarnings({ "removal", "deprecation" })
public static Map<String, ParsedPersistenceXmlDescriptor> parse(
URL persistenceXmlUrl,
PersistenceUnitTransactionType transactionType,
Map integration) {
Map<?,?> integration) {
PersistenceXmlParser parser = new PersistenceXmlParser(
ClassLoaderServiceImpl.fromConfigSettings( integration ),
transactionType
@ -212,6 +213,7 @@ public class PersistenceXmlParser {
private final PersistenceUnitTransactionType defaultTransactionType;
private final Map<String, ParsedPersistenceXmlDescriptor> persistenceUnits;
@SuppressWarnings("removal")
protected PersistenceXmlParser(ClassLoaderService classLoaderService, PersistenceUnitTransactionType defaultTransactionType) {
this.classLoaderService = classLoaderService;
this.defaultTransactionType = defaultTransactionType;
@ -222,7 +224,7 @@ public class PersistenceXmlParser {
return new ArrayList<>(persistenceUnits.values());
}
private void doResolve(Map integration) {
private void doResolve(Map<?,?> integration) {
final List<URL> xmlUrls = classLoaderService.locateResources( "META-INF/persistence.xml" );
if ( xmlUrls.isEmpty() ) {
LOG.unableToFindPersistenceXmlInClasspath();
@ -232,97 +234,146 @@ public class PersistenceXmlParser {
}
}
private void parsePersistenceXml(List<URL> xmlUrls, Map integration) {
private void parsePersistenceXml(List<URL> xmlUrls, Map<?,?> integration) {
for ( URL xmlUrl : xmlUrls ) {
parsePersistenceXml( xmlUrl, integration );
}
}
protected void parsePersistenceXml(URL xmlUrl, Map integration) {
protected void parsePersistenceXml(URL xmlUrl, Map<?,?> integration) {
if ( LOG.isTraceEnabled() ) {
LOG.tracef( "Attempting to parse persistence.xml file : %s", xmlUrl.toExternalForm() );
}
final Document doc = loadUrl( xmlUrl );
final Element top = doc.getDocumentElement();
final URL persistenceUnitRootUrl = ArchiveHelper.getJarURLFromURLEntry( xmlUrl, "/META-INF/persistence.xml" );
final NodeList children = top.getChildNodes();
for ( int i = 0; i < children.getLength() ; i++ ) {
if ( children.item( i ).getNodeType() == Node.ELEMENT_NODE ) {
final Element element = (Element) children.item( i );
final String tag = element.getTagName();
if ( tag.equals( "persistence-unit" ) ) {
final URL puRootUrl = ArchiveHelper.getJarURLFromURLEntry( xmlUrl, "/META-INF/persistence.xml" );
ParsedPersistenceXmlDescriptor persistenceUnit = new ParsedPersistenceXmlDescriptor( puRootUrl );
bindPersistenceUnit( persistenceUnit, element );
final JaxbPersistenceImpl jaxbPersistence = loadUrlWithJaxb( xmlUrl );
final List<JaxbPersistenceImpl.JaxbPersistenceUnitImpl> jaxbPersistenceUnits = jaxbPersistence.getPersistenceUnit();
if ( persistenceUnits.containsKey( persistenceUnit.getName() ) ) {
LOG.duplicatedPersistenceUnitName( persistenceUnit.getName() );
continue;
}
for ( int i = 0; i < jaxbPersistenceUnits.size(); i++ ) {
final JaxbPersistenceImpl.JaxbPersistenceUnitImpl jaxbPersistenceUnit = jaxbPersistenceUnits.get( i );
// per JPA spec, any settings passed in to PersistenceProvider bootstrap methods should override
// values found in persistence.xml
if ( integration.containsKey( AvailableSettings.JAKARTA_PERSISTENCE_PROVIDER ) ) {
persistenceUnit.setProviderClassName( (String) integration.get( AvailableSettings.JAKARTA_PERSISTENCE_PROVIDER ) );
}
else if ( integration.containsKey( AvailableSettings.JPA_PERSISTENCE_PROVIDER ) ) {
DeprecationLogger.DEPRECATION_LOGGER.deprecatedSetting(
AvailableSettings.JPA_PERSISTENCE_PROVIDER,
AvailableSettings.JAKARTA_PERSISTENCE_PROVIDER
);
persistenceUnit.setProviderClassName( (String) integration.get( AvailableSettings.JPA_PERSISTENCE_PROVIDER ) );
}
if ( persistenceUnits.containsKey( jaxbPersistenceUnit.getName() ) ) {
LOG.duplicatedPersistenceUnitName( jaxbPersistenceUnit.getName() );
continue;
}
if ( integration.containsKey( AvailableSettings.JPA_TRANSACTION_TYPE ) ) {
DeprecationLogger.DEPRECATION_LOGGER.deprecatedSetting(
AvailableSettings.JPA_TRANSACTION_TYPE,
AvailableSettings.JAKARTA_TRANSACTION_TYPE
);
String transactionType = (String) integration.get( AvailableSettings.JPA_TRANSACTION_TYPE );
persistenceUnit.setTransactionType( parseTransactionType( transactionType ) );
}
else if ( integration.containsKey( AvailableSettings.JAKARTA_TRANSACTION_TYPE ) ) {
String transactionType = (String) integration.get( AvailableSettings.JAKARTA_TRANSACTION_TYPE );
persistenceUnit.setTransactionType( parseTransactionType( transactionType ) );
}
final ParsedPersistenceXmlDescriptor persistenceUnitDescriptor = new ParsedPersistenceXmlDescriptor(
persistenceUnitRootUrl );
bindPersistenceUnit( jaxbPersistenceUnit, persistenceUnitDescriptor );
if ( integration.containsKey( AvailableSettings.JPA_JTA_DATASOURCE ) ) {
DeprecationLogger.DEPRECATION_LOGGER.deprecatedSetting(
AvailableSettings.JPA_JTA_DATASOURCE,
AvailableSettings.JAKARTA_JTA_DATASOURCE
);
persistenceUnit.setJtaDataSource( integration.get( AvailableSettings.JPA_JTA_DATASOURCE ) );
}
else if ( integration.containsKey( AvailableSettings.JAKARTA_JTA_DATASOURCE ) ) {
persistenceUnit.setJtaDataSource( integration.get( AvailableSettings.JAKARTA_JTA_DATASOURCE ) );
}
// per JPA spec, any settings passed in to PersistenceProvider bootstrap methods should override
// values found in persistence.xml
applyIntegrationOverrides( integration, persistenceUnitDescriptor );
if ( integration.containsKey( AvailableSettings.JPA_NON_JTA_DATASOURCE ) ) {
DeprecationLogger.DEPRECATION_LOGGER.deprecatedSetting(
AvailableSettings.JPA_NON_JTA_DATASOURCE,
AvailableSettings.JAKARTA_NON_JTA_DATASOURCE
);
persistenceUnit.setNonJtaDataSource( integration.get( AvailableSettings.JPA_NON_JTA_DATASOURCE ) );
}
else if ( integration.containsKey( AvailableSettings.JAKARTA_NON_JTA_DATASOURCE ) ) {
persistenceUnit.setNonJtaDataSource( integration.get( AvailableSettings.JAKARTA_NON_JTA_DATASOURCE ) );
}
persistenceUnits.put( persistenceUnitDescriptor.getName(), persistenceUnitDescriptor );
}
}
decodeTransactionType( persistenceUnit );
private void bindPersistenceUnit(
JaxbPersistenceImpl.JaxbPersistenceUnitImpl jaxbPersistenceUnit,
ParsedPersistenceXmlDescriptor persistenceUnitDescriptor) {
final String name = jaxbPersistenceUnit.getName();
if ( StringHelper.isNotEmpty( name ) ) {
LOG.tracef( "Persistence unit name from persistence.xml : %s", name );
persistenceUnitDescriptor.setName( name );
}
Properties properties = persistenceUnit.getProperties();
ConfigurationHelper.overrideProperties( properties, integration );
//noinspection removal
final PersistenceUnitTransactionType transactionType = jaxbPersistenceUnit.getTransactionType();
if ( transactionType != null ) {
persistenceUnitDescriptor.setTransactionType( transactionType );
}
persistenceUnits.put( persistenceUnit.getName(), persistenceUnit );
}
persistenceUnitDescriptor.setProviderClassName( jaxbPersistenceUnit.getProvider() );
persistenceUnitDescriptor.setNonJtaDataSource( jaxbPersistenceUnit.getNonJtaDataSource() );
persistenceUnitDescriptor.setJtaDataSource( jaxbPersistenceUnit.getJtaDataSource() );
persistenceUnitDescriptor.setSharedCacheMode( jaxbPersistenceUnit.getSharedCacheMode() );
persistenceUnitDescriptor.setValidationMode( jaxbPersistenceUnit.getValidationMode() );
persistenceUnitDescriptor.setExcludeUnlistedClasses( handleBoolean( jaxbPersistenceUnit.isExcludeUnlistedClasses(), false ) );
persistenceUnitDescriptor.addClasses( jaxbPersistenceUnit.getClasses() );
persistenceUnitDescriptor.addMappingFiles( jaxbPersistenceUnit.getMappingFiles() );
persistenceUnitDescriptor.addJarFileUrls( jaxbPersistenceUnit.getJarFiles() );
final JaxbPropertiesImpl propertyContainer = jaxbPersistenceUnit.getPropertyContainer();
if ( propertyContainer != null ) {
for ( JaxbPropertyImpl property : propertyContainer.getProperties() ) {
persistenceUnitDescriptor.getProperties().put(
property.getName(),
property.getValue()
);
}
}
}
private void decodeTransactionType(ParsedPersistenceXmlDescriptor persistenceUnit) {
// if transaction type is set already
// use that value
private boolean handleBoolean(Boolean incoming, boolean fallback) {
if ( incoming != null ) {
return incoming;
}
return fallback;
}
@SuppressWarnings("deprecation")
private void applyIntegrationOverrides(Map<?,?> integration, ParsedPersistenceXmlDescriptor persistenceUnitDescriptor) {
if ( integration.containsKey( AvailableSettings.JAKARTA_PERSISTENCE_PROVIDER ) ) {
persistenceUnitDescriptor.setProviderClassName( (String) integration.get( AvailableSettings.JAKARTA_PERSISTENCE_PROVIDER ) );
}
else if ( integration.containsKey( AvailableSettings.JPA_PERSISTENCE_PROVIDER ) ) {
DeprecationLogger.DEPRECATION_LOGGER.deprecatedSetting(
AvailableSettings.JPA_PERSISTENCE_PROVIDER,
AvailableSettings.JAKARTA_PERSISTENCE_PROVIDER
);
persistenceUnitDescriptor.setProviderClassName( (String) integration.get( AvailableSettings.JPA_PERSISTENCE_PROVIDER ) );
}
if ( integration.containsKey( AvailableSettings.JPA_TRANSACTION_TYPE ) ) {
DeprecationLogger.DEPRECATION_LOGGER.deprecatedSetting(
AvailableSettings.JPA_TRANSACTION_TYPE,
AvailableSettings.JAKARTA_TRANSACTION_TYPE
);
String transactionType = (String) integration.get( AvailableSettings.JPA_TRANSACTION_TYPE );
persistenceUnitDescriptor.setTransactionType( parseTransactionType( transactionType ) );
}
else if ( integration.containsKey( AvailableSettings.JAKARTA_TRANSACTION_TYPE ) ) {
String transactionType = (String) integration.get( AvailableSettings.JAKARTA_TRANSACTION_TYPE );
persistenceUnitDescriptor.setTransactionType( parseTransactionType( transactionType ) );
}
if ( integration.containsKey( AvailableSettings.JPA_JTA_DATASOURCE ) ) {
DeprecationLogger.DEPRECATION_LOGGER.deprecatedSetting(
AvailableSettings.JPA_JTA_DATASOURCE,
AvailableSettings.JAKARTA_JTA_DATASOURCE
);
persistenceUnitDescriptor.setJtaDataSource( integration.get( AvailableSettings.JPA_JTA_DATASOURCE ) );
}
else if ( integration.containsKey( AvailableSettings.JAKARTA_JTA_DATASOURCE ) ) {
persistenceUnitDescriptor.setJtaDataSource( integration.get( AvailableSettings.JAKARTA_JTA_DATASOURCE ) );
}
if ( integration.containsKey( AvailableSettings.JPA_NON_JTA_DATASOURCE ) ) {
DeprecationLogger.DEPRECATION_LOGGER.deprecatedSetting(
AvailableSettings.JPA_NON_JTA_DATASOURCE,
AvailableSettings.JAKARTA_NON_JTA_DATASOURCE
);
persistenceUnitDescriptor.setNonJtaDataSource( integration.get( AvailableSettings.JPA_NON_JTA_DATASOURCE ) );
}
else if ( integration.containsKey( AvailableSettings.JAKARTA_NON_JTA_DATASOURCE ) ) {
persistenceUnitDescriptor.setNonJtaDataSource( integration.get( AvailableSettings.JAKARTA_NON_JTA_DATASOURCE ) );
}
applyTransactionTypeOverride( persistenceUnitDescriptor );
final Properties properties = persistenceUnitDescriptor.getProperties();
ConfigurationHelper.overrideProperties( properties, integration );
}
@SuppressWarnings("removal")
private void applyTransactionTypeOverride(ParsedPersistenceXmlDescriptor persistenceUnitDescriptor) {
// if transaction type is set already, use that value
if ( persistenceUnitDescriptor.getTransactionType() != null ) {
return;
}
// else
// if JTA DS
// use JTA
@ -330,121 +381,18 @@ public class PersistenceXmlParser {
// use RESOURCE_LOCAL
// else
// use defaultTransactionType
if ( persistenceUnit.getTransactionType() != null ) {
return;
if ( persistenceUnitDescriptor.getJtaDataSource() != null ) {
persistenceUnitDescriptor.setTransactionType( PersistenceUnitTransactionType.JTA );
}
if ( persistenceUnit.getJtaDataSource() != null ) {
persistenceUnit.setTransactionType( PersistenceUnitTransactionType.JTA );
}
else if ( persistenceUnit.getNonJtaDataSource() != null ) {
persistenceUnit.setTransactionType( PersistenceUnitTransactionType.RESOURCE_LOCAL );
else if ( persistenceUnitDescriptor.getNonJtaDataSource() != null ) {
persistenceUnitDescriptor.setTransactionType( PersistenceUnitTransactionType.RESOURCE_LOCAL );
}
else {
persistenceUnit.setTransactionType( defaultTransactionType );
persistenceUnitDescriptor.setTransactionType( defaultTransactionType );
}
}
private void bindPersistenceUnit(ParsedPersistenceXmlDescriptor persistenceUnit, Element persistenceUnitElement) {
final String name = persistenceUnitElement.getAttribute( "name" );
if ( StringHelper.isNotEmpty( name ) ) {
LOG.tracef( "Persistence unit name from persistence.xml : %s", name );
persistenceUnit.setName( name );
}
final PersistenceUnitTransactionType transactionType = parseTransactionType(
persistenceUnitElement.getAttribute( "transaction-type" )
);
if ( transactionType != null ) {
persistenceUnit.setTransactionType( transactionType );
}
NodeList children = persistenceUnitElement.getChildNodes();
for ( int i = 0; i < children.getLength() ; i++ ) {
if ( children.item( i ).getNodeType() == Node.ELEMENT_NODE ) {
Element element = (Element) children.item( i );
String tag = element.getTagName();
if ( tag.equals( "non-jta-data-source" ) ) {
persistenceUnit.setNonJtaDataSource( extractContent( element ) );
}
else if ( tag.equals( "jta-data-source" ) ) {
persistenceUnit.setJtaDataSource( extractContent( element ) );
}
else if ( tag.equals( "provider" ) ) {
persistenceUnit.setProviderClassName( extractContent( element ) );
}
else if ( tag.equals( "class" ) ) {
persistenceUnit.addClasses( extractContent( element ) );
}
else if ( tag.equals( "mapping-file" ) ) {
persistenceUnit.addMappingFiles( extractContent( element ) );
}
else if ( tag.equals( "jar-file" ) ) {
persistenceUnit.addJarFileUrl( ArchiveHelper.getURLFromPath( extractContent( element ) ) );
}
else if ( tag.equals( "exclude-unlisted-classes" ) ) {
persistenceUnit.setExcludeUnlistedClasses( extractBooleanContent(element, true) );
}
else if ( tag.equals( "delimited-identifiers" ) ) {
persistenceUnit.setUseQuotedIdentifiers( true );
}
else if ( tag.equals( "validation-mode" ) ) {
persistenceUnit.setValidationMode( extractContent( element ) );
}
else if ( tag.equals( "shared-cache-mode" ) ) {
persistenceUnit.setSharedCacheMode( extractContent( element ) );
}
else if ( tag.equals( "properties" ) ) {
NodeList props = element.getChildNodes();
for ( int j = 0; j < props.getLength() ; j++ ) {
if ( props.item( j ).getNodeType() == Node.ELEMENT_NODE ) {
Element propElement = (Element) props.item( j );
if ( !"property".equals( propElement.getTagName() ) ) {
continue;
}
String propName = propElement.getAttribute( "name" ).trim();
String propValue = propElement.getAttribute( "value" ).trim();
if ( propValue.isEmpty() ) {
//fall back to the natural (Hibernate) way of description
propValue = extractContent( propElement, "" );
}
persistenceUnit.getProperties().put( propName, propValue );
}
}
}
}
}
}
private static String extractContent(Element element) {
return extractContent( element, null );
}
private static String extractContent(Element element, String defaultStr) {
if ( element == null ) {
return defaultStr;
}
NodeList children = element.getChildNodes();
StringBuilder result = new StringBuilder();
for ( int i = 0; i < children.getLength() ; i++ ) {
if ( children.item( i ).getNodeType() == Node.TEXT_NODE ||
children.item( i ).getNodeType() == Node.CDATA_SECTION_NODE ) {
result.append( children.item( i ).getNodeValue() );
}
}
return result.toString().trim();
}
private static boolean extractBooleanContent(Element element, boolean defaultBool) {
String content = extractContent( element );
if (content != null && content.length() > 0) {
return Boolean.valueOf(content);
}
return defaultBool;
}
@SuppressWarnings("removal")
private static PersistenceUnitTransactionType parseTransactionType(String value) {
if ( StringHelper.isEmpty( value ) ) {
return null;
@ -460,32 +408,21 @@ public class PersistenceXmlParser {
}
}
private Document loadUrl(URL xmlUrl) {
private JaxbPersistenceImpl loadUrlWithJaxb(URL xmlUrl) {
final String resourceName = xmlUrl.toExternalForm();
try {
URLConnection conn = xmlUrl.openConnection();
conn.setUseCaches( false ); //avoid JAR locking on Windows and Tomcat
try {
try (InputStream inputStream = conn.getInputStream()) {
final InputSource inputSource = new InputSource( inputStream );
try {
DocumentBuilder documentBuilder = documentBuilderFactory().newDocumentBuilder();
try {
Document document = documentBuilder.parse( inputSource );
validate( document );
return document;
}
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
);
}
}
// avoid JAR locking on Windows and Tomcat
conn.setUseCaches( false );
try (InputStream inputStream = conn.getInputStream()) {
final StreamSource inputSource = new StreamSource( inputStream );
final ConfigurationBinder configurationBinder = new ConfigurationBinder( classLoaderService );
final Binding<JaxbPersistenceImpl> binding = configurationBinder.bind(
inputSource,
new Origin( SourceType.URL, resourceName )
);
return binding.getRoot();
}
catch (IOException e) {
throw new PersistenceException( "Unable to obtain input stream from [" + resourceName + "]", e );
@ -496,82 +433,4 @@ public class PersistenceXmlParser {
}
}
/**
* Validate the document using the
*/
private void validate(Document document) {
// todo : add ability to disable validation...
final String version = document.getDocumentElement().getAttribute( "version" );
final Validator validator = new ConfigXsdSupport().jpaXsd( version ).getSchema().newValidator();
List<SAXException> errors = new ArrayList<>();
validator.setErrorHandler( new ErrorHandlerImpl( errors ) );
try {
validator.validate( new DOMSource( document ) );
}
catch (SAXException e) {
errors.add( e );
}
catch (IOException e) {
throw new PersistenceException( "Unable to validate persistence.xml", e );
}
if ( errors.size() != 0 ) {
//report all errors in the exception
StringBuilder errorMessage = new StringBuilder( );
for ( SAXException error : errors ) {
errorMessage.append( extractInfo( error ) ).append( '\n' );
}
throw new PersistenceException( "Invalid persistence.xml.\n" + errorMessage.toString() );
}
}
private DocumentBuilderFactory documentBuilderFactory;
private DocumentBuilderFactory documentBuilderFactory() {
if ( documentBuilderFactory == null ) {
documentBuilderFactory = buildDocumentBuilderFactory();
}
return documentBuilderFactory;
}
private DocumentBuilderFactory buildDocumentBuilderFactory() {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware( true );
return documentBuilderFactory;
}
public static class ErrorHandlerImpl implements ErrorHandler {
private List<SAXException> errors;
ErrorHandlerImpl(List<SAXException> errors) {
this.errors = errors;
}
public void error(SAXParseException error) {
errors.add( error );
}
public void fatalError(SAXParseException error) {
errors.add( error );
}
public void warning(SAXParseException warn) {
if ( LOG.isTraceEnabled() ) {
LOG.trace( extractInfo( warn ) );
}
}
}
private static String extractInfo(SAXException error) {
if ( error instanceof SAXParseException ) {
return "Error parsing XML [line : " + ( (SAXParseException) error ).getLineNumber()
+ ", column : " + ( (SAXParseException) error ).getColumnNumber()
+ "] : " + error.getMessage();
}
else {
return "Error parsing XML : " + error.getMessage();
}
}
}

View File

@ -20,6 +20,49 @@
<anonymousTypeName prefix="Jaxb" suffix="Impl"/>
</nameXmlTransform>
</schemaBindings>
</bindings>
<bindings node="//xsd:element[@name='persistence-unit']/xsd:complexType">
<bindings node=".//xsd:element[@name='mapping-file']">
<property name="mappingFiles"/>
</bindings>
<bindings node=".//xsd:element[@name='class']">
<property name="classes"/>
</bindings>
<bindings node=".//xsd:element[@name='jar-file']">
<property name="jarFiles"/>
</bindings>
<bindings node=".//xsd:element[@name='properties']">
<property name="propertyContainer"/>
<bindings node=".//xsd:element[@name='property']">
<property name="properties"/>
</bindings>
</bindings>
</bindings>
<!--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ Marshalling of enum values
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-->
<bindings node="//xsd:simpleType[@name='persistence-unit-transaction-type']">
<javaType name="jakarta.persistence.spi.PersistenceUnitTransactionType"
parseMethod="org.hibernate.boot.jaxb.cfg.internal.TransactionTypeMarshalling.fromXml"
printMethod="org.hibernate.boot.jaxb.cfg.internal.TransactionTypeMarshalling.toXml" />
</bindings>
<bindings node="//xsd:simpleType[@name='persistence-unit-caching-type']">
<javaType name="jakarta.persistence.SharedCacheMode"
parseMethod="org.hibernate.boot.jaxb.cfg.internal.SharedCacheModeMarshalling.fromXml"
printMethod="org.hibernate.boot.jaxb.cfg.internal.SharedCacheModeMarshalling.toXml" />
</bindings>
<bindings node="//xsd:simpleType[@name='persistence-unit-validation-mode-type']">
<javaType name="jakarta.persistence.ValidationMode"
parseMethod="org.hibernate.boot.jaxb.cfg.internal.ValidationModeMarshalling.fromXml"
printMethod="org.hibernate.boot.jaxb.cfg.internal.ValidationModeMarshalling.toXml" />
</bindings>
</bindings>
</bindings>

View File

@ -70,9 +70,6 @@ public class JpaDescriptorParser {
private static final String DEFAULT_ORM_XML_LOCATION = "/META-INF/orm.xml";
private static final String SERIALIZATION_FILE_NAME = "Hibernate-Static-Metamodel-Generator.tmp";
private static final String PERSISTENCE_SCHEMA = "org/hibernate/xsd/cfg/persistence_3_0.xsd";
private final Context context;
private final List<JaxbEntityMappingsImpl> entityMappings;
private final XmlParserHelper xmlParserHelper;
@ -121,7 +118,7 @@ public class JpaDescriptorParser {
// get mapping file names from persistence.xml
List<JaxbPersistenceImpl.JaxbPersistenceUnitImpl> persistenceUnits = persistence.getPersistenceUnit();
for ( JaxbPersistenceImpl.JaxbPersistenceUnitImpl unit : persistenceUnits ) {
mappingFileNames.addAll( unit.getMappingFile() );
mappingFileNames.addAll( unit.getMappingFiles() );
}
}