HHH-8015 Spring 3.2.1 cannot be deployed on JBoss AS7 with Hibernate 4.1.6 due to class loader issues.

This commit is contained in:
Strong Liu 2013-02-18 23:39:23 +08:00
parent 52f2edfa45
commit a6c46408df
3 changed files with 208 additions and 122 deletions

View File

@ -494,6 +494,14 @@ public interface AvailableSettings {
*/
public static final String NON_CONTEXTUAL_LOB_CREATION = "hibernate.jdbc.lob.non_contextual_creation";
/**
* Used to define a {@link java.util.Collection} of the {@link ClassLoader} instances Hibernate should use for
* class-loading and resource-lookups.
*
* @since 4.2
*/
public static final String CLASSLOADERS = "hibernate.classLoaders";
/**
* Names the {@link ClassLoader} used to load user application classes.
* @since 4.0

View File

@ -23,11 +23,14 @@
*/
package org.hibernate.service;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import org.hibernate.integrator.internal.IntegratorServiceImpl;
import org.hibernate.integrator.spi.Integrator;
import org.hibernate.service.classloading.internal.ClassLoaderServiceImpl;
import org.hibernate.service.classloading.spi.ClassLoaderService;
import org.hibernate.service.internal.BootstrapServiceRegistryImpl;
/**
@ -40,10 +43,8 @@ import org.hibernate.service.internal.BootstrapServiceRegistryImpl;
*/
public class BootstrapServiceRegistryBuilder {
private final LinkedHashSet<Integrator> providedIntegrators = new LinkedHashSet<Integrator>();
private ClassLoader applicationClassLoader;
private ClassLoader resourcesClassLoader;
private ClassLoader hibernateClassLoader;
private ClassLoader environmentClassLoader;
private List<ClassLoader> providedClassLoaders;
private ClassLoaderService providedClassLoaderService;
/**
* Add an {@link Integrator} to be applied to the bootstrap registry.
@ -61,23 +62,56 @@ public class BootstrapServiceRegistryBuilder {
*
* @param classLoader The class loader to use
* @return {@code this}, for method chaining
*
* @deprecated Use {@link #with(ClassLoader)} instead
*/
@SuppressWarnings( {"UnusedDeclaration"})
@Deprecated
public BootstrapServiceRegistryBuilder withApplicationClassLoader(ClassLoader classLoader) {
this.applicationClassLoader = classLoader;
return with( classLoader );
}
/**
* Adds a provided {@link ClassLoader} for use in class-loading and resource-lookup
*
* @param classLoader The class loader to use
*
* @return {@code this}, for method chaining
*/
public BootstrapServiceRegistryBuilder with(ClassLoader classLoader) {
if ( providedClassLoaders == null ) {
providedClassLoaders = new ArrayList<ClassLoader>();
}
providedClassLoaders.add( classLoader );
return this;
}
/**
* Adds a provided {@link ClassLoaderService} for use in class-loading and resource-lookup
*
* @param classLoaderService The class loader to use
*
* @return {@code this}, for method chaining
*/
public BootstrapServiceRegistryBuilder with(ClassLoaderService classLoaderService) {
providedClassLoaderService = classLoaderService;
return this;
}
/**
* Applies the specified {@link ClassLoader} as the resource class loader for the bootstrap registry
*
* @param classLoader The class loader to use
* @return {@code this}, for method chaining
*
* @deprecated Use {@link #with(ClassLoader)} instead
*/
@Deprecated
@SuppressWarnings( {"UnusedDeclaration"})
public BootstrapServiceRegistryBuilder withResourceClassLoader(ClassLoader classLoader) {
this.resourcesClassLoader = classLoader;
return this;
return with( classLoader );
}
/**
@ -85,11 +119,13 @@ public class BootstrapServiceRegistryBuilder {
*
* @param classLoader The class loader to use
* @return {@code this}, for method chaining
*
* @deprecated Use {@link #with(ClassLoader)} instead
*/
@SuppressWarnings( {"UnusedDeclaration"})
@Deprecated
public BootstrapServiceRegistryBuilder withHibernateClassLoader(ClassLoader classLoader) {
this.hibernateClassLoader = classLoader;
return this;
return with( classLoader );
}
/**
@ -97,11 +133,13 @@ public class BootstrapServiceRegistryBuilder {
*
* @param classLoader The class loader to use
* @return {@code this}, for method chaining
*
* @deprecated Use {@link #with(ClassLoader)} instead
*/
@SuppressWarnings( {"UnusedDeclaration"})
@Deprecated
public BootstrapServiceRegistryBuilder withEnvironmentClassLoader(ClassLoader classLoader) {
this.environmentClassLoader = classLoader;
return this;
return with( classLoader );
}
/**
@ -110,12 +148,12 @@ public class BootstrapServiceRegistryBuilder {
* @return The built bootstrap registry
*/
public BootstrapServiceRegistry build() {
final ClassLoaderServiceImpl classLoaderService = new ClassLoaderServiceImpl(
applicationClassLoader,
resourcesClassLoader,
hibernateClassLoader,
environmentClassLoader
);
final ClassLoaderService classLoaderService;
if ( providedClassLoaderService == null ) {
classLoaderService = new ClassLoaderServiceImpl( providedClassLoaders );
} else {
classLoaderService = providedClassLoaderService;
}
final IntegratorServiceImpl integratorService = new IntegratorServiceImpl(
providedIntegrators,

View File

@ -27,6 +27,9 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
@ -35,6 +38,8 @@ 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.service.classloading.spi.ClassLoaderService;
import org.hibernate.service.classloading.spi.ClassLoadingException;
@ -45,74 +50,74 @@ import org.hibernate.service.classloading.spi.ClassLoadingException;
* @author Steve Ebersole
*/
public class ClassLoaderServiceImpl implements ClassLoaderService {
private final ClassLoader classClassLoader;
private final ClassLoader resourcesClassLoader;
private static final Logger log = Logger.getLogger( ClassLoaderServiceImpl.class );
private final ClassLoader aggregatedClassLoader;
public ClassLoaderServiceImpl() {
this( ClassLoaderServiceImpl.class.getClassLoader() );
}
public ClassLoaderServiceImpl(ClassLoader classLoader) {
this( classLoader, classLoader, classLoader, classLoader );
this( Collections.singletonList( classLoader ) );
}
public ClassLoaderServiceImpl(
ClassLoader applicationClassLoader,
ClassLoader resourcesClassLoader,
ClassLoader hibernateClassLoader,
ClassLoader environmentClassLoader) {
// Normalize missing loaders
if ( hibernateClassLoader == null ) {
hibernateClassLoader = ClassLoaderServiceImpl.class.getClassLoader();
}
public ClassLoaderServiceImpl(List<ClassLoader> providedClassLoaders) {
final LinkedHashSet<ClassLoader> orderedClassLoaderSet = new LinkedHashSet<ClassLoader>();
if ( environmentClassLoader == null || applicationClassLoader == null ) {
ClassLoader sysClassLoader = locateSystemClassLoader();
ClassLoader tccl = locateTCCL();
if ( environmentClassLoader == null ) {
environmentClassLoader = sysClassLoader != null ? sysClassLoader : hibernateClassLoader;
}
if ( applicationClassLoader == null ) {
applicationClassLoader = tccl != null ? tccl : hibernateClassLoader;
}
}
if ( resourcesClassLoader == null ) {
resourcesClassLoader = applicationClassLoader;
}
final LinkedHashSet<ClassLoader> classLoadingClassLoaders = new LinkedHashSet<ClassLoader>();
classLoadingClassLoaders.add( applicationClassLoader );
classLoadingClassLoaders.add( hibernateClassLoader );
classLoadingClassLoaders.add( environmentClassLoader );
this.classClassLoader = new ClassLoader(null) {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
for ( ClassLoader loader : classLoadingClassLoaders ) {
try {
return loader.loadClass( name );
}
catch (Exception ignore) {
}
// first add all provided class loaders, if any
if ( providedClassLoaders != null ) {
for ( ClassLoader classLoader : providedClassLoaders ) {
if ( classLoader != null ) {
orderedClassLoaderSet.add( classLoader );
}
throw new ClassNotFoundException( "Could not load requested class : " + name );
}
};
}
this.resourcesClassLoader = resourcesClassLoader;
// normalize adding known class-loaders...
// first the Hibernate class loader
orderedClassLoaderSet.add( ClassLoaderServiceImpl.class.getClassLoader() );
// then the TCCL, if one...
final ClassLoader tccl = locateTCCL();
if ( tccl != null ) {
orderedClassLoaderSet.add( tccl );
}
// finally the system classloader
final ClassLoader sysClassLoader = locateSystemClassLoader();
if ( sysClassLoader != null ) {
orderedClassLoaderSet.add( sysClassLoader );
}
// now build the aggregated class loader...
this.aggregatedClassLoader = new AggregatedClassLoader( orderedClassLoaderSet );
}
@SuppressWarnings( {"UnusedDeclaration"})
@SuppressWarnings({"UnusedDeclaration", "unchecked", "deprecation"})
@Deprecated
public static ClassLoaderServiceImpl fromConfigSettings(Map configVales) {
return new ClassLoaderServiceImpl(
(ClassLoader) configVales.get( AvailableSettings.APP_CLASSLOADER ),
(ClassLoader) configVales.get( AvailableSettings.RESOURCES_CLASSLOADER ),
(ClassLoader) configVales.get( AvailableSettings.HIBERNATE_CLASSLOADER ),
(ClassLoader) configVales.get( AvailableSettings.ENVIRONMENT_CLASSLOADER )
);
final List<ClassLoader> providedClassLoaders = new ArrayList<ClassLoader>();
final Collection<ClassLoader> classLoaders = (Collection<ClassLoader>) configVales.get( AvailableSettings.CLASSLOADERS );
if ( classLoaders != null ) {
for ( ClassLoader classLoader : classLoaders ) {
providedClassLoaders.add( classLoader );
}
}
addIfSet( providedClassLoaders, AvailableSettings.APP_CLASSLOADER, configVales );
addIfSet( providedClassLoaders, AvailableSettings.RESOURCES_CLASSLOADER, configVales );
addIfSet( providedClassLoaders, AvailableSettings.HIBERNATE_CLASSLOADER, configVales );
addIfSet( providedClassLoaders, AvailableSettings.ENVIRONMENT_CLASSLOADER, configVales );
return new ClassLoaderServiceImpl( providedClassLoaders );
}
private static void addIfSet(List<ClassLoader> providedClassLoaders, String name, Map configVales) {
final ClassLoader providedClassLoader = (ClassLoader) configVales.get( name );
if ( providedClassLoader != null ) {
providedClassLoaders.add( providedClassLoader );
}
}
private static ClassLoader locateSystemClassLoader() {
try {
return ClassLoader.getSystemClassLoader();
@ -135,7 +140,7 @@ public class ClassLoaderServiceImpl implements ClassLoaderService {
@SuppressWarnings( {"unchecked"})
public <T> Class<T> classForName(String className) {
try {
return (Class<T>) Class.forName( className, true, classClassLoader );
return (Class<T>) Class.forName( className, true, aggregatedClassLoader );
}
catch (Exception e) {
throw new ClassLoadingException( "Unable to load class [" + className + "]", e );
@ -152,7 +157,7 @@ public class ClassLoaderServiceImpl implements ClassLoaderService {
}
try {
return resourcesClassLoader.getResource( name );
return aggregatedClassLoader.getResource( name );
}
catch ( Exception ignore ) {
}
@ -164,17 +169,43 @@ public class ClassLoaderServiceImpl implements ClassLoaderService {
public InputStream locateResourceStream(String name) {
// first we try name as a URL
try {
log.tracef( "trying via [new URL(\"%s\")]", name );
return new URL( name ).openStream();
}
catch ( Exception ignore ) {
}
try {
return resourcesClassLoader.getResourceAsStream( name );
log.tracef( "trying via [ClassLoader.getResourceAsStream(\"%s\")]", name );
InputStream stream = aggregatedClassLoader.getResourceAsStream( name );
if ( stream != null ) {
return stream;
}
}
catch ( Exception ignore ) {
}
final String stripped = name.startsWith( "/" ) ? name.substring(1) : null;
if ( stripped != null ) {
try {
log.tracef( "trying via [new URL(\"%s\")]", stripped );
return new URL( stripped ).openStream();
}
catch ( Exception ignore ) {
}
try {
log.tracef( "trying via [ClassLoader.getResourceAsStream(\"%s\")]", stripped );
InputStream stream = aggregatedClassLoader.getResourceAsStream( stripped );
if ( stream != null ) {
return stream;
}
}
catch ( Exception ignore ) {
}
}
return null;
}
@ -182,7 +213,7 @@ public class ClassLoaderServiceImpl implements ClassLoaderService {
public List<URL> locateResources(String name) {
ArrayList<URL> urls = new ArrayList<URL>();
try {
Enumeration<URL> urlEnumeration = resourcesClassLoader.getResources( name );
Enumeration<URL> urlEnumeration = aggregatedClassLoader.getResources( name );
if ( urlEnumeration != null && urlEnumeration.hasMoreElements() ) {
while ( urlEnumeration.hasMoreElements() ) {
urls.add( urlEnumeration.nextElement() );
@ -197,56 +228,7 @@ public class ClassLoaderServiceImpl implements ClassLoaderService {
@Override
public <S> LinkedHashSet<S> loadJavaServices(Class<S> serviceContract) {
final ClassLoader serviceLoaderClassLoader = new ClassLoader(null) {
final ClassLoader[] classLoaderArray = new ClassLoader[] {
// first look on the hibernate class loader
getClass().getClassLoader(),
// next look on the resource class loader
resourcesClassLoader,
// finally look on the combined class class loader
classClassLoader
};
@Override
public Enumeration<URL> getResources(String name) throws IOException {
final HashSet<URL> resourceUrls = new HashSet<URL>();
for ( ClassLoader classLoader : classLoaderArray ) {
final Enumeration<URL> urls = classLoader.getResources( name );
while ( urls.hasMoreElements() ) {
resourceUrls.add( urls.nextElement() );
}
}
return new Enumeration<URL>() {
final Iterator<URL> resourceUrlIterator = resourceUrls.iterator();
@Override
public boolean hasMoreElements() {
return resourceUrlIterator.hasNext();
}
@Override
public URL nextElement() {
return resourceUrlIterator.next();
}
};
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
for ( ClassLoader classLoader : classLoaderArray ) {
try {
return classLoader.loadClass( name );
}
catch (Exception ignore) {
}
}
throw new ClassNotFoundException( "Could not load requested class : " + name );
}
};
final ServiceLoader<S> loader = ServiceLoader.load( serviceContract, serviceLoaderClassLoader );
final ServiceLoader<S> loader = ServiceLoader.load( serviceContract, aggregatedClassLoader );
final LinkedHashSet<S> services = new LinkedHashSet<S>();
for ( S service : loader ) {
services.add( service );
@ -254,4 +236,62 @@ public class ClassLoaderServiceImpl implements ClassLoaderService {
return services;
}
private static class AggregatedClassLoader extends ClassLoader {
private final ClassLoader[] individualClassLoaders;
private AggregatedClassLoader(final LinkedHashSet<ClassLoader> orderedClassLoaderSet) {
super( null );
individualClassLoaders = orderedClassLoaderSet.toArray( new ClassLoader[ orderedClassLoaderSet.size() ] );
}
@Override
public Enumeration<URL> getResources(String name) throws IOException {
final HashSet<URL> resourceUrls = new HashSet<URL>();
for ( ClassLoader classLoader : individualClassLoaders ) {
final Enumeration<URL> urls = classLoader.getResources( name );
while ( urls.hasMoreElements() ) {
resourceUrls.add( urls.nextElement() );
}
}
return new Enumeration<URL>() {
final Iterator<URL> resourceUrlIterator = resourceUrls.iterator();
@Override
public boolean hasMoreElements() {
return resourceUrlIterator.hasNext();
}
@Override
public URL nextElement() {
return resourceUrlIterator.next();
}
};
}
@Override
protected URL findResource(String name) {
for ( ClassLoader classLoader : individualClassLoaders ) {
final URL resource = classLoader.getResource( name );
if ( resource != null ) {
return resource;
}
}
return super.findResource( name );
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
for ( ClassLoader classLoader : individualClassLoaders ) {
try {
return classLoader.loadClass( name );
}
catch (Exception ignore) {
}
}
throw new ClassNotFoundException( "Could not load requested class : " + name );
}
}
}