Browse Source

Allow TestCompiler DynamicClassLoader to resolve '.class' resources

Update `DynamicClassLoader` so that `findResource(...)` also considered
compiled class bytecode.

Closes gh-29347
pull/29310/head
Phillip Webb 2 years ago
parent
commit
327eec09ae
  1. 30
      spring-core-test/src/main/java/org/springframework/core/test/tools/DynamicClassLoader.java
  2. 10
      spring-core-test/src/test/java/org/springframework/core/test/tools/TestCompilerTests.java

30
spring-core-test/src/main/java/org/springframework/core/test/tools/DynamicClassLoader.java

@ -31,6 +31,7 @@ import java.util.function.Supplier; @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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,

10
spring-core-test/src/test/java/org/springframework/core/test/tools/TestCompilerTests.java

@ -16,6 +16,7 @@ @@ -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 { @@ -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!");
}

Loading…
Cancel
Save