MethodHandles.Lookup.defineResource?
Peter Levart
peter.levart at gmail.com
Wed Aug 29 16:20:43 UTC 2018
Hi Stephen,
On 08/28/2018 11:21 PM, Stephen Colebourne wrote:
>> So is there a way to achieve what you want for your test with existing API?
> Probably. I could have a separate maven module creating a separate
> modular jar file with the testing resource in it, and run the test
> using both the classpath mode and modulepath. I'm not going to be
> doing that as the benefits are too low compared to the cost.
The cost is not that big if you for example create yourself a reusable
utility. You don't need to create maven modules etc., just to have a
named or unnamed module participating in your test.
Say you have the following library class you want to test (this should
be equivalent to your ExampleMarketDataBuilder):
import java.io.IOException;
import java.io.InputStream;
import java.io.UncheckedIOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
public class ResUtil {
public static String readResource(ClassLoader classLoader, String
resName) {
URL url = classLoader.getResource(resName);
return url == null ? null : readUrl(url);
}
public static String readResource(Class<?> clazz, String resName) {
URL url = clazz.getResource(resName);
return url == null ? null : readUrl(url);
}
private static String readUrl(URL url) {
try (InputStream in = url.openStream()) {
byte[] bytes = in.readAllBytes();
return new String(bytes, StandardCharsets.UTF_8);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
You can test it in both modes with the following test:
import lib.ResUtil;
import si.pele.layerbuilder.ModuleLayerBuilder;
import java.net.URLClassLoader;
public class ResTest {
public static void main(String[] args) throws Exception {
ModuleLayerBuilder builder = new ModuleLayerBuilder();
builder
.module("my.mod", mb -> mb
.resource(
"module-info.java",
"module my.mod {",
" opens my.pkg;",
"}"
)
.resource(
"my/pkg/Test.java",
"package my.pkg;",
"public class Test {",
"}"
)
.resource(
"my/pkg/readme.txt",
"HELLO WORLD!"
)
);
// test using "--class-path"
try (URLClassLoader loader = builder.buildClassLoader()) {
Class<?> testClass = Class.forName("my.pkg.Test", false,
loader);
System.out.println("Resolving in --class-path artifact via
ClassLoader gives: " + ResUtil.readResource(loader, "my/pkg/readme.txt"));
System.out.println("Resolving in --class-path artifact via
Class gives: " + ResUtil.readResource(testClass, "readme.txt"));
}
// test using "--module-path"
{
ModuleLayer layer = builder.buildModuleLayer();
Module myMod = layer.findModule("my.mod").orElseThrow(() ->
new RuntimeException("Can't find module: my.mod"));
ClassLoader loader = myMod.getClassLoader();
Class<?> testClass = Class.forName("my.pkg.Test", false,
loader);
System.out.println("Resolving in --module-path artifact via
ClassLoader gives: " + ResUtil.readResource(loader, "my/pkg/readme.txt"));
System.out.println("Resolving in --module-path artifact via
Class gives: " + ResUtil.readResource(testClass, "readme.txt"));
}
}
}
A ModuleLayerBuilder utility is not that complicated given all the
API(s) that are available in JDK 9+. Here it is (you can adapt it to
your needs if you want):
http://cr.openjdk.java.net/~plevart/misc/ModuleLayerBuilder/ModuleLayerBuilder.java
Regards, Peter
More information about the core-libs-dev
mailing list