HHH-13551 Test the retrieval of a service when an "incompatible" classloader is provided
This commit is contained in:
parent
5174fc28dc
commit
f2f788c03d
|
@ -8,8 +8,11 @@ package org.hibernate.boot.registry.classloading.internal;
|
|||
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
@ -124,6 +127,28 @@ public class ClassLoaderServiceImplTest {
|
|||
csi.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestForIssue(jiraKey = "HHH-13551")
|
||||
public void testServiceFromIncompatibleClassLoader() {
|
||||
ClassLoaderServiceImpl classLoaderService = new ClassLoaderServiceImpl(
|
||||
Arrays.asList(
|
||||
getClass().getClassLoader(),
|
||||
/*
|
||||
* This classloader will return instances of MyService where MyService
|
||||
* is a different object than the one we manipulate in the current classloader.
|
||||
* This used to throw an exception that triggered a boot failure in ORM,
|
||||
* but should now be ignored.
|
||||
*/
|
||||
new IsolatedClassLoader( getClass().getClassLoader() )
|
||||
),
|
||||
TcclLookupPrecedence.AFTER
|
||||
);
|
||||
|
||||
Collection<MyService> loadedServices = classLoaderService.loadJavaServices( MyService.class );
|
||||
|
||||
assertEquals( 1, loadedServices.size() );
|
||||
}
|
||||
|
||||
private static class InternalClassLoader extends ClassLoader {
|
||||
private List<String> names = new ArrayList<>( );
|
||||
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* 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.registry.classloading.internal;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import org.hibernate.bytecode.spi.ByteCodeHelper;
|
||||
|
||||
/**
|
||||
* A classloader isolated from the application classloader,
|
||||
* simulating a separate classloader that can create duplicate classes.
|
||||
* This can result in a Service implementation extending
|
||||
* a Service interface that is essentially the same as the one manipulated by ORM,
|
||||
* but is a different Class instance and is thus deemed different by the JVM.
|
||||
*/
|
||||
class IsolatedClassLoader extends ClassLoader {
|
||||
/**
|
||||
* Another classloader from which resources will be read.
|
||||
* Classes available in that classloader will be duplicated in the isolated classloader.
|
||||
*/
|
||||
private final ClassLoader resourceSource;
|
||||
|
||||
IsolatedClassLoader(ClassLoader resourceSource) {
|
||||
super( getTopLevelClassLoader( resourceSource ) );
|
||||
this.resourceSource = resourceSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
InputStream is = getResourceAsStream( name.replace( '.', '/' ) + ".class" );
|
||||
if ( is == null ) {
|
||||
throw new ClassNotFoundException( name + " not found" );
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] bytecode = ByteCodeHelper.readByteCode( is );
|
||||
return defineClass( name, bytecode, 0, bytecode.length );
|
||||
}
|
||||
catch( Throwable t ) {
|
||||
throw new ClassNotFoundException( name + " not found", t );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getResource(String name) {
|
||||
return resourceSource.getResource( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<URL> getResources(String name) throws IOException {
|
||||
return resourceSource.getResources( name );
|
||||
}
|
||||
|
||||
private static ClassLoader getTopLevelClassLoader(ClassLoader classFileSource) {
|
||||
ClassLoader result = classFileSource;
|
||||
while ( result.getParent() != null ) {
|
||||
result = result.getParent();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -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
|
||||
*/
|
||||
package org.hibernate.boot.registry.classloading.internal;
|
||||
|
||||
import org.hibernate.service.Service;
|
||||
|
||||
public interface MyService extends Service {
|
||||
}
|
|
@ -0,0 +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
|
||||
*/
|
||||
package org.hibernate.boot.registry.classloading.internal;
|
||||
|
||||
public class MyServiceImpl implements MyService {
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.hibernate.boot.registry.classloading.internal.MyServiceImpl
|
Loading…
Reference in New Issue