From 394458f6a65fcfafa5ca225755347f23c8324661 Mon Sep 17 00:00:00 2001 From: Brett Meyer Date: Thu, 28 Feb 2013 10:28:02 -0500 Subject: [PATCH] HHH-8010 Support app-managed EntityManagerFactory and SessionFactory creation by OSGi bundles Conflicts: hibernate-core/src/main/java/org/hibernate/boot/registry/classloading/internal/ClassLoaderServiceImpl.java hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DriverManagerConnectionProviderImpl.java hibernate-entitymanager/src/main/java/org/hibernate/ejb/Ejb3Configuration.java hibernate-osgi/src/main/java/org/hibernate/osgi/HibernateBundleActivator.java --- .../internal/ClassLoaderServiceImpl.java | 15 ++++-- .../java/org/hibernate/cfg/Configuration.java | 10 +++- .../org/hibernate/engine/jdbc/BlobProxy.java | 2 +- .../org/hibernate/engine/jdbc/ClobProxy.java | 2 +- .../org/hibernate/engine/jdbc/NClobProxy.java | 2 +- .../engine/jdbc/ResultSetWrapperProxy.java | 2 +- .../engine/jdbc/SerializableBlobProxy.java | 2 +- .../engine/jdbc/SerializableClobProxy.java | 2 +- .../DriverManagerConnectionProviderImpl.java | 47 ++++++++++++------- .../internal/util/ClassLoaderHelper.java | 4 +- .../hibernate/internal/util/ConfigHelper.java | 6 +-- .../internal/util/ReflectHelper.java | 4 +- .../internal/util/SerializationHelper.java | 2 +- .../internal/util/xml/XMLHelper.java | 2 +- .../DriverManagerRegistrationTest.java | 2 +- .../infinispan/InfinispanRegionFactory.java | 2 +- 16 files changed, 68 insertions(+), 38 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/boot/registry/classloading/internal/ClassLoaderServiceImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/registry/classloading/internal/ClassLoaderServiceImpl.java index dc2b5c301b..ccba37c693 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/registry/classloading/internal/ClassLoaderServiceImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/registry/classloading/internal/ClassLoaderServiceImpl.java @@ -37,11 +37,11 @@ import java.util.List; import java.util.Map; import java.util.ServiceLoader; -import org.jboss.logging.Logger; - -import org.hibernate.cfg.AvailableSettings; import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.internal.util.ClassLoaderHelper; +import org.jboss.logging.Logger; /** * Standard implementation of the service for interacting with class loaders @@ -74,7 +74,14 @@ public class ClassLoaderServiceImpl implements ClassLoaderService { } // normalize adding known class-loaders... - // first the Hibernate class loader + // first, the "overridden" classloader provided by an environment (OSGi, etc.) + // TODO: This should probably be wired into BootstrapServiceRegistryBuilder + // instead, however that wasn't available in 4.2. Once JPA 2.1 is testable + // in an OSGi container, move this and re-work. + if ( ClassLoaderHelper.overridenClassLoader != null ) { + orderedClassLoaderSet.add( ClassLoaderHelper.overridenClassLoader ); + } + // then the Hibernate class loader orderedClassLoaderSet.add( ClassLoaderServiceImpl.class.getClassLoader() ); // then the TCCL, if one... final ClassLoader tccl = locateTCCL(); diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java b/hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java index cb3b2879a1..dbd12237ca 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/Configuration.java @@ -723,7 +723,7 @@ public class Configuration implements Serializable { */ public Configuration addResource(String resourceName) throws MappingException { LOG.readingMappingsFromResource( resourceName ); - ClassLoader contextClassLoader = ClassLoaderHelper.getClassLoader(); + ClassLoader contextClassLoader = ClassLoaderHelper.getContextClassLoader(); InputStream resourceInputStream = null; if ( contextClassLoader != null ) { resourceInputStream = contextClassLoader.getResourceAsStream( resourceName ); @@ -1305,6 +1305,11 @@ public class Configuration implements Serializable { protected void secondPassCompile() throws MappingException { LOG.trace( "Starting secondPassCompile() processing" ); + + // TEMPORARY + // Ensure the correct ClassLoader is used in commons-annotations. + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader( ClassLoaderHelper.getContextClassLoader() ); //process default values first { @@ -1382,6 +1387,7 @@ public class Configuration implements Serializable { buildUniqueKeyFromColumnNames( table, keyName, holder.getColumns() ); } } + for(Table table : jpaIndexHoldersByTable.keySet()){ final List jpaIndexHolders = jpaIndexHoldersByTable.get( table ); int uniqueIndexPerTable = 0; @@ -1393,6 +1399,8 @@ public class Configuration implements Serializable { buildUniqueKeyFromColumnNames( table, keyName, holder.getColumns(), holder.getOrdering(), holder.isUnique() ); } } + + Thread.currentThread().setContextClassLoader( tccl ); } private void processSecondPassesOfType(Class type) { diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/BlobProxy.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/BlobProxy.java index 54fd38430d..3475b2310c 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/BlobProxy.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/BlobProxy.java @@ -197,7 +197,7 @@ public class BlobProxy implements InvocationHandler { * @return The class loader appropriate for proxy construction. */ private static ClassLoader getProxyClassLoader() { - ClassLoader cl = ClassLoaderHelper.getClassLoader(); + ClassLoader cl = ClassLoaderHelper.getContextClassLoader(); if ( cl == null ) { cl = BlobImplementer.class.getClassLoader(); } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/ClobProxy.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/ClobProxy.java index 97fbe4cc26..f45489f2d9 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/ClobProxy.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/ClobProxy.java @@ -216,7 +216,7 @@ public class ClobProxy implements InvocationHandler { * @return The class loader appropriate for proxy construction. */ protected static ClassLoader getProxyClassLoader() { - ClassLoader cl = ClassLoaderHelper.getClassLoader(); + ClassLoader cl = ClassLoaderHelper.getContextClassLoader(); if ( cl == null ) { cl = ClobImplementer.class.getClassLoader(); } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/NClobProxy.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/NClobProxy.java index 9afdd80207..4f9227891d 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/NClobProxy.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/NClobProxy.java @@ -88,7 +88,7 @@ public class NClobProxy extends ClobProxy { * @return The class loader appropriate for proxy construction. */ protected static ClassLoader getProxyClassLoader() { - ClassLoader cl = ClassLoaderHelper.getClassLoader(); + ClassLoader cl = ClassLoaderHelper.getContextClassLoader(); if ( cl == null ) { cl = NClobImplementer.class.getClassLoader(); } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/ResultSetWrapperProxy.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/ResultSetWrapperProxy.java index 8609ba53f8..4b0b21ea3f 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/ResultSetWrapperProxy.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/ResultSetWrapperProxy.java @@ -79,7 +79,7 @@ public class ResultSetWrapperProxy implements InvocationHandler { * @return The class loader appropriate for proxy construction. */ public static ClassLoader getProxyClassLoader() { - ClassLoader cl = ClassLoaderHelper.getClassLoader(); + ClassLoader cl = ClassLoaderHelper.getContextClassLoader(); if ( cl == null ) { cl = ResultSet.class.getClassLoader(); } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/SerializableBlobProxy.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/SerializableBlobProxy.java index 160f49f76e..0d8209ef72 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/SerializableBlobProxy.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/SerializableBlobProxy.java @@ -102,7 +102,7 @@ public class SerializableBlobProxy implements InvocationHandler, Serializable { * @return The class loader appropriate for proxy construction. */ public static ClassLoader getProxyClassLoader() { - ClassLoader cl = ClassLoaderHelper.getClassLoader(); + ClassLoader cl = ClassLoaderHelper.getContextClassLoader(); if ( cl == null ) { cl = WrappedBlob.class.getClassLoader(); } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/SerializableClobProxy.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/SerializableClobProxy.java index ef991f4871..8b499e5c25 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/SerializableClobProxy.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/SerializableClobProxy.java @@ -101,7 +101,7 @@ public class SerializableClobProxy implements InvocationHandler, Serializable { * @return The class loader appropriate for proxy construction. */ public static ClassLoader getProxyClassLoader() { - ClassLoader cl = ClassLoaderHelper.getClassLoader(); + ClassLoader cl = ClassLoaderHelper.getContextClassLoader(); if ( cl == null ) { cl = WrappedClob.class.getClassLoader(); } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DriverManagerConnectionProviderImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DriverManagerConnectionProviderImpl.java index 6fd2f82c20..df83684145 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DriverManagerConnectionProviderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DriverManagerConnectionProviderImpl.java @@ -24,6 +24,7 @@ package org.hibernate.engine.jdbc.connections.internal; import java.sql.Connection; +import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.ArrayList; @@ -31,9 +32,9 @@ import java.util.Map; import java.util.Properties; import java.util.concurrent.atomic.AtomicInteger; -import org.jboss.logging.Logger; - import org.hibernate.HibernateException; +import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; +import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.Environment; import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider; @@ -41,12 +42,11 @@ import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.config.ConfigurationHelper; import org.hibernate.service.UnknownUnwrapTypeException; -import org.hibernate.boot.registry.classloading.spi.ClassLoaderService; -import org.hibernate.boot.registry.classloading.spi.ClassLoadingException; import org.hibernate.service.spi.Configurable; import org.hibernate.service.spi.ServiceRegistryAwareService; import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.Stoppable; +import org.jboss.logging.Logger; /** * A connection provider that uses the {@link java.sql.DriverManager} directly to open connections and provides @@ -74,6 +74,8 @@ public class DriverManagerConnectionProviderImpl private boolean stopped; private transient ServiceRegistryImplementor serviceRegistry; + + private Driver driver; @Override public boolean isUnwrappableAs(Class unwrapType) { @@ -102,12 +104,14 @@ public class DriverManagerConnectionProviderImpl } else if ( serviceRegistry != null ) { try { - serviceRegistry.getService( ClassLoaderService.class ).classForName( driverClassName ); + driver = (Driver) serviceRegistry.getService( + ClassLoaderService.class ).classForName( driverClassName ) + .newInstance(); } - catch ( ClassLoadingException e ) { + catch ( Exception e ) { throw new ClassLoadingException( - "Specified JDBC Driver " + driverClassName + " class not found", - e + "Specified JDBC Driver " + driverClassName + + " could not be loaded", e ); } } @@ -115,14 +119,14 @@ public class DriverManagerConnectionProviderImpl else { try { // trying via forName() first to be as close to DriverManager's semantics - Class.forName( driverClassName ); + driver = (Driver) Class.forName( driverClassName ).newInstance(); } - catch ( ClassNotFoundException cnfe ) { + catch ( Exception e1 ) { try{ - ReflectHelper.classForName( driverClassName ); + driver = (Driver) ReflectHelper.classForName( driverClassName ).newInstance(); } - catch ( ClassNotFoundException e ) { - throw new HibernateException( "Specified JDBC Driver " + driverClassName + " class not found", e ); + catch ( Exception e2 ) { + throw new HibernateException( "Specified JDBC Driver " + driverClassName + " could not be loaded", e2 ); } } } @@ -191,11 +195,22 @@ public class DriverManagerConnectionProviderImpl } // otherwise we open a new connection... - final boolean debugEnabled = LOG.isDebugEnabled(); if ( debugEnabled ) LOG.debug( "Opening new JDBC connection" ); - - Connection conn = DriverManager.getConnection( url, connectionProps ); + + Connection conn; + if ( driver != null ) { + // If a Driver is available, completely circumvent + // DriverManager#getConnection. It attempts to double check + // ClassLoaders before using a Driver. This does not work well in + // OSGi environments without wonky workarounds. + conn = driver.connect( url, connectionProps ); + } + else { + // If no Driver, fall back on the original method. + conn = DriverManager.getConnection( url, connectionProps ); + } + if ( isolation != null ) { conn.setTransactionIsolation( isolation.intValue() ); } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/ClassLoaderHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/ClassLoaderHelper.java index ea6b7fdb15..78e2f85826 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/ClassLoaderHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/ClassLoaderHelper.java @@ -22,7 +22,7 @@ package org.hibernate.internal.util; /** * This exists purely to allow custom ClassLoaders to be injected and used - * prior to ServiceRegistry and ClassLoadingService existance. This should be + * prior to ServiceRegistry and ClassLoadingService existence. This should be * replaced in Hibernate 5. * * @author Brett Meyer @@ -31,7 +31,7 @@ public class ClassLoaderHelper { public static ClassLoader overridenClassLoader = null; - public static ClassLoader getClassLoader() { + public static ClassLoader getContextClassLoader() { return overridenClassLoader != null ? overridenClassLoader : Thread.currentThread().getContextClassLoader(); } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/ConfigHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/ConfigHelper.java index dacda973c2..3cd79bdb99 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/ConfigHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/ConfigHelper.java @@ -78,7 +78,7 @@ public final class ConfigHelper { // First, try to locate this resource through the current // context classloader. - ClassLoader contextClassLoader = ClassLoaderHelper.getClassLoader(); + ClassLoader contextClassLoader = ClassLoaderHelper.getContextClassLoader(); if (contextClassLoader!=null) { url = contextClassLoader.getResource(path); } @@ -159,7 +159,7 @@ public final class ConfigHelper { resource.substring(1) : resource; InputStream stream = null; - ClassLoader classLoader = ClassLoaderHelper.getClassLoader(); + ClassLoader classLoader = ClassLoaderHelper.getContextClassLoader(); if (classLoader!=null) { stream = classLoader.getResourceAsStream( stripped ); } @@ -182,7 +182,7 @@ public final class ConfigHelper { InputStream stream = null; - ClassLoader classLoader = ClassLoaderHelper.getClassLoader(); + ClassLoader classLoader = ClassLoaderHelper.getContextClassLoader(); if ( classLoader != null ) { stream = classLoader.getResourceAsStream( resource ); if ( stream == null && hasLeadingSlash ) { diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java index 5d0ab0f774..ea13163a22 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java @@ -160,7 +160,7 @@ public final class ReflectHelper { */ public static Class classForName(String name, Class caller) throws ClassNotFoundException { try { - ClassLoader classLoader = ClassLoaderHelper.getClassLoader(); + ClassLoader classLoader = ClassLoaderHelper.getContextClassLoader(); if ( classLoader != null ) { return classLoader.loadClass( name ); } @@ -182,7 +182,7 @@ public final class ReflectHelper { */ public static Class classForName(String name) throws ClassNotFoundException { try { - ClassLoader classLoader = ClassLoaderHelper.getClassLoader(); + ClassLoader classLoader = ClassLoaderHelper.getContextClassLoader(); if ( classLoader != null ) { return classLoader.loadClass(name); } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/SerializationHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/SerializationHelper.java index 541a63e4e9..a8d89e9b08 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/SerializationHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/SerializationHelper.java @@ -191,7 +191,7 @@ public final class SerializationHelper { * @return The current TCCL */ public static ClassLoader defaultClassLoader() { - return ClassLoaderHelper.getClassLoader(); + return ClassLoaderHelper.getContextClassLoader(); } public static ClassLoader hibernateClassLoader() { diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/XMLHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/xml/XMLHelper.java index 3c35db7563..e44b9a30d6 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/xml/XMLHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/xml/XMLHelper.java @@ -82,7 +82,7 @@ public final class XMLHelper { public static DocumentFactory getDocumentFactory() { - ClassLoader cl = ClassLoaderHelper.getClassLoader(); + ClassLoader cl = ClassLoaderHelper.getContextClassLoader(); DocumentFactory factory; try { Thread.currentThread().setContextClassLoader( XMLHelper.class.getClassLoader() ); diff --git a/hibernate-core/src/test/java/org/hibernate/connection/DriverManagerRegistrationTest.java b/hibernate-core/src/test/java/org/hibernate/connection/DriverManagerRegistrationTest.java index cb902559f3..9bb4798a72 100644 --- a/hibernate-core/src/test/java/org/hibernate/connection/DriverManagerRegistrationTest.java +++ b/hibernate-core/src/test/java/org/hibernate/connection/DriverManagerRegistrationTest.java @@ -92,7 +92,7 @@ public class DriverManagerRegistrationTest extends BaseUnitTestCase { } private static ClassLoader determineClassLoader() { - ClassLoader cl = ClassLoaderHelper.getClassLoader(); + ClassLoader cl = ClassLoaderHelper.getContextClassLoader(); if ( cl == null ) { cl = DriverManagerRegistrationTest.class.getClassLoader(); } diff --git a/hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java b/hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java index 8faa3c9e2c..3a35625ec0 100644 --- a/hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java +++ b/hibernate-infinispan/src/main/java/org/hibernate/cache/infinispan/InfinispanRegionFactory.java @@ -387,7 +387,7 @@ public class InfinispanRegionFactory implements RegionFactory { try { String configLoc = ConfigurationHelper.getString( INFINISPAN_CONFIG_RESOURCE_PROP, properties, DEF_INFINISPAN_CONFIG_RESOURCE); - ClassLoader classLoader = ClassLoaderHelper.getClassLoader(); + ClassLoader classLoader = ClassLoaderHelper.getContextClassLoader(); InputStream is = FileLookupFactory.newInstance().lookupFileStrict( configLoc, classLoader); ParserRegistry parserRegistry = new ParserRegistry(classLoader);