Allow TestCompiler DynamicClassLoader to resolve '.class' resources
Update `DynamicClassLoader` so that `findResource(...)` also considered compiled class bytecode. Closes gh-29347
This commit is contained in:
@@ -31,6 +31,7 @@ import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
@@ -91,15 +92,7 @@ public class DynamicClassLoader extends ClassLoader {
|
||||
return super.findClass(name);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private byte[] findClassBytes(String name) {
|
||||
ClassFile classFile = this.classFiles.get(name);
|
||||
if (classFile != null) {
|
||||
return classFile.getContent();
|
||||
}
|
||||
DynamicClassFileObject dynamicClassFile = this.dynamicClassFiles.get(name);
|
||||
return (dynamicClassFile != null) ? dynamicClassFile.getBytes() : null;
|
||||
}
|
||||
|
||||
|
||||
private Class<?> defineClass(String name, byte[] bytes) {
|
||||
if (this.defineClassMethod != null) {
|
||||
@@ -109,7 +102,6 @@ public class DynamicClassLoader extends ClassLoader {
|
||||
return defineClass(name, bytes, 0, bytes.length);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Enumeration<URL> findResources(String name) throws IOException {
|
||||
URL resource = findResource(name);
|
||||
@@ -122,6 +114,14 @@ public class DynamicClassLoader extends ClassLoader {
|
||||
@Override
|
||||
@Nullable
|
||||
protected URL findResource(String name) {
|
||||
if (name.endsWith(ClassUtils.CLASS_FILE_SUFFIX)) {
|
||||
String className = ClassUtils.convertResourcePathToClassName(name.substring(0,
|
||||
name.length() - ClassUtils.CLASS_FILE_SUFFIX.length()));
|
||||
byte[] classBytes = findClassBytes(className);
|
||||
if (classBytes != null) {
|
||||
return createResourceUrl(name, () -> classBytes);
|
||||
}
|
||||
}
|
||||
ResourceFile resourceFile = this.resourceFiles.get(name);
|
||||
if (resourceFile != null) {
|
||||
return createResourceUrl(resourceFile.getPath(), resourceFile::getBytes);
|
||||
@@ -133,6 +133,16 @@ public class DynamicClassLoader extends ClassLoader {
|
||||
return super.findResource(name);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private byte[] findClassBytes(String name) {
|
||||
ClassFile classFile = this.classFiles.get(name);
|
||||
if (classFile != null) {
|
||||
return classFile.getContent();
|
||||
}
|
||||
DynamicClassFileObject dynamicClassFile = this.dynamicClassFiles.get(name);
|
||||
return (dynamicClassFile != null) ? dynamicClassFile.getBytes() : null;
|
||||
}
|
||||
|
||||
private URL createResourceUrl(String name, Supplier<byte[]> bytesSupplier) {
|
||||
try {
|
||||
return new URL(null, "resource:///" + name,
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.core.test.tools;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -278,6 +279,15 @@ class TestCompilerTests {
|
||||
compiled.getInstance(PublicInterface.class, "com.example.Test").perform()).isEqualTo("Hello from subpackage"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getResourceForCompiledBytecode() {
|
||||
SourceFile sourceFile = SourceFile.of(HELLO_WORLD);
|
||||
TestCompiler.forSystem().compile(sourceFile, compiled -> {
|
||||
InputStream stream = compiled.getClassLoader().getResourceAsStream("com/example/Hello.class");
|
||||
assertThat(stream).isNotNull();
|
||||
});
|
||||
}
|
||||
|
||||
private void assertSuppliesHelloWorld(Compiled compiled) {
|
||||
assertThat(compiled.getInstance(Supplier.class).get()).isEqualTo("Hello World!");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user