package org.hibernate.jpa;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceException;
import javax.persistence.spi.LoadState;
import javax.persistence.spi.PersistenceProvider;
import javax.persistence.spi.PersistenceUnitInfo;
import javax.persistence.spi.ProviderUtil;
import org.hibernate.jpa.boot.internal.ParsedPersistenceXmlDescriptor;
import org.hibernate.jpa.boot.internal.PersistenceUnitInfoDescriptor;
import org.hibernate.jpa.boot.internal.PersistenceXmlParser;
import org.hibernate.jpa.boot.spi.Bootstrap;
import org.hibernate.jpa.boot.spi.EntityManagerFactoryBuilder;
import org.hibernate.jpa.boot.spi.PersistenceUnitDescriptor;
import org.hibernate.jpa.boot.spi.ProviderChecker;
import org.hibernate.jpa.internal.util.PersistenceUtilHelper;
import org.jboss.logging.Logger;
public class HibernatePersistenceProvider implements PersistenceProvider {
private static final Logger log = Logger.getLogger( HibernatePersistenceProvider.class );
private final PersistenceUtilHelper.MetadataCache cache = new PersistenceUtilHelper.MetadataCache();
@Override
public EntityManagerFactory createEntityManagerFactory(String persistenceUnitName, Map properties) {
log.tracef( "Starting createEntityManagerFactory for persistenceUnitName %s", persistenceUnitName );
try {
final EntityManagerFactoryBuilder builder = getEntityManagerFactoryBuilderOrNull( persistenceUnitName, properties );
if ( builder == null ) {
log.trace( "Could not obtain matching EntityManagerFactoryBuilder, returning null" );
return null;
}
else {
return builder.build();
}
}
catch (PersistenceException pe) {
throw pe;
}
catch (Exception e) {
log.debug( "Unable to build entity manager factory", e );
throw new PersistenceException( "Unable to build entity manager factory", e );
}
}
protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilderOrNull(String persistenceUnitName, Map properties) {
return getEntityManagerFactoryBuilderOrNull( persistenceUnitName, properties, null );
}
protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilderOrNull(String persistenceUnitName, Map properties, ClassLoader providedClassLoader) {
log.tracef( "Attempting to obtain correct EntityManagerFactoryBuilder for persistenceUnitName : %s", persistenceUnitName );
final Map integration = wrap( properties );
final List<ParsedPersistenceXmlDescriptor> units;
try {
units = PersistenceXmlParser.locatePersistenceUnits( integration );
}
catch (Exception e) {
log.debug( "Unable to locate persistence units", e );
throw new PersistenceException( "Unable to locate persistence units", e );
}
log.debugf( "Located and parsed %s persistence units; checking each", units.size() );
if ( persistenceUnitName == null && units.size() > 1 ) {
throw new PersistenceException( "No name provided and multiple persistence units found" );
}
for ( ParsedPersistenceXmlDescriptor persistenceUnit : units ) {
log.debugf(
"Checking persistence-unit [name=%s, explicit-provider=%s] against incoming persistence unit name [%s]",
persistenceUnit.getName(),
persistenceUnit.getProviderClassName(),
persistenceUnitName
);
final boolean matches = persistenceUnitName == null || persistenceUnit.getName().equals( persistenceUnitName );
if ( !matches ) {
log.debug( "Excluding from consideration due to name mis-match" );
continue;
}
if ( ! ProviderChecker.isProvider( persistenceUnit, properties ) ) {
log.debug( "Excluding from consideration due to provider mis-match" );
continue;
}
return getEntityManagerFactoryBuilder( persistenceUnit, integration, providedClassLoader );
}
log.debug( "Found no matching persistence units" );
return null;
}
@SuppressWarnings("unchecked")
protected static Map wrap(Map properties) {
return properties == null ? Collections.emptyMap() : Collections.unmodifiableMap( properties );
}
@Override
public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map properties) {
log.tracef( "Starting createContainerEntityManagerFactory : %s", info.getPersistenceUnitName() );
return getEntityManagerFactoryBuilder( info, properties ).build();
}
@Override
public void generateSchema(PersistenceUnitInfo info, Map map) {
log.tracef( "Starting generateSchema : PUI.name=%s", info.getPersistenceUnitName() );
final EntityManagerFactoryBuilder builder = getEntityManagerFactoryBuilder( info, map );
builder.generateSchema();
}
@Override
public boolean generateSchema(String persistenceUnitName, Map map) {
log.tracef( "Starting generateSchema for persistenceUnitName %s", persistenceUnitName );
final EntityManagerFactoryBuilder builder = getEntityManagerFactoryBuilderOrNull( persistenceUnitName, map );
if ( builder == null ) {
log.trace( "Could not obtain matching EntityManagerFactoryBuilder, returning false" );
return false;
}
builder.generateSchema();
return true;
}
private EntityManagerFactoryBuilder getEntityManagerFactoryBuilder(PersistenceUnitInfo info, Map integration) {
return getEntityManagerFactoryBuilder( new PersistenceUnitInfoDescriptor( info ), integration, null );
}
protected EntityManagerFactoryBuilder getEntityManagerFactoryBuilder(PersistenceUnitDescriptor persistenceUnitDescriptor,
Map integration, ClassLoader providedClassLoader) {
return Bootstrap.getEntityManagerFactoryBuilder( persistenceUnitDescriptor, integration, providedClassLoader );
}
private final ProviderUtil providerUtil = new ProviderUtil() {
@Override
public LoadState isLoadedWithoutReference(Object proxy, String property) {
return PersistenceUtilHelper.isLoadedWithoutReference( proxy, property, cache );
}
@Override
public LoadState isLoadedWithReference(Object proxy, String property) {
return PersistenceUtilHelper.isLoadedWithReference( proxy, property, cache );
}
@Override
public LoadState isLoaded(Object o) {
return PersistenceUtilHelper.isLoaded(o);
}
};
@Override
public ProviderUtil getProviderUtil() {
return providerUtil;
}
}