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.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
@ -124,6 +127,28 @@ public class ClassLoaderServiceImplTest {
|
||||||
csi.stop();
|
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 static class InternalClassLoader extends ClassLoader {
|
||||||
private List<String> names = new ArrayList<>( );
|
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