From 89817c5624e680b46279985616140fcdc1d67420 Mon Sep 17 00:00:00 2001 From: Walter Oggioni Date: Thu, 9 Jan 2025 16:13:38 +0800 Subject: [PATCH] added JPMS URL stream handler --- .gitea/workflows/build.yaml | 3 +- build.gradle | 4 +- gradle.properties | 4 +- jwo-test-module/build.gradle | 7 +++ .../src/main/java/module-info.java | 3 ++ .../src/main/java/my/test/resource/Foo.java | 4 ++ .../main/resources/my/test/resource/file.txt | 1 + jwo-test/build.gradle | 31 +++++++++++ jwo-test/src/test/java/module-info.java | 6 +++ .../net/woggioni/jwo/test/JpmsUrlTest.java | 29 +++++++++++ settings.gradle | 8 +-- .../woggioni/jwo/UncloseableOutputStream.java | 4 +- .../net/woggioni/jwo/UncloseableWriter.java | 4 +- src/main/java9/module-info.java | 1 + .../net/woggioni/jwo/url/jpms/Handler.java | 52 +++++++++++++++++++ .../net/woggioni/jwo/url/JpmsUrlTest.java | 26 ++++++++++ 16 files changed, 176 insertions(+), 11 deletions(-) create mode 100644 jwo-test-module/build.gradle create mode 100644 jwo-test-module/src/main/java/module-info.java create mode 100644 jwo-test-module/src/main/java/my/test/resource/Foo.java create mode 100644 jwo-test-module/src/main/resources/my/test/resource/file.txt create mode 100644 jwo-test/build.gradle create mode 100644 jwo-test/src/test/java/module-info.java create mode 100644 jwo-test/src/test/java/net/woggioni/jwo/test/JpmsUrlTest.java create mode 100644 src/main/java9/net/woggioni/jwo/url/jpms/Handler.java create mode 100644 src/test/java/net/woggioni/jwo/url/JpmsUrlTest.java diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index 62d63f7..97d24a8 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -8,7 +8,8 @@ jobs: steps: - name: Checkout sources uses: actions/checkout@v4 - - uses: actions/setup-java@v4 + - name: Setup Java + uses: actions/setup-java@v4 with: distribution: graalvm java-version: 21 diff --git a/build.gradle b/build.gradle index b296121..0a20713 100644 --- a/build.gradle +++ b/build.gradle @@ -27,6 +27,7 @@ allprojects { } dependencies { + testRuntimeOnly project(':jwo-test-module') testImplementation catalog.junit.jupiter.api testImplementation catalog.junit.jupiter.params testRuntimeOnly catalog.junit.jupiter.engine @@ -97,7 +98,6 @@ ext { setProperty('jpms.module.name', 'net.woggioni.jwo') } - configurations { pathClassloaderTest zipTestBundle { @@ -144,5 +144,3 @@ test { '--add-opens', 'java.base/sun.nio.fs=ALL-UNNAMED', ]) } - - diff --git a/gradle.properties b/gradle.properties index 045d73b..2f632d7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,6 +3,6 @@ org.gradle.parallel=true org.gradle.caching=true gitea.maven.url = https://gitea.woggioni.net/api/packages/woggioni/maven -jwo.version = 2024.12.31 -lys.version = 2024.12.28 +jwo.version = 2025.01.09 +lys.version = 2025.01.08 guice.version = 5.0.1 diff --git a/jwo-test-module/build.gradle b/jwo-test-module/build.gradle new file mode 100644 index 0000000..ed03488 --- /dev/null +++ b/jwo-test-module/build.gradle @@ -0,0 +1,7 @@ +plugins { + id 'java-library' +} + +java { + modularity.inferModulePath = true +} diff --git a/jwo-test-module/src/main/java/module-info.java b/jwo-test-module/src/main/java/module-info.java new file mode 100644 index 0000000..8c21739 --- /dev/null +++ b/jwo-test-module/src/main/java/module-info.java @@ -0,0 +1,3 @@ +open module net.woggioni.jwo.test.module { + exports my.test.resource; +} \ No newline at end of file diff --git a/jwo-test-module/src/main/java/my/test/resource/Foo.java b/jwo-test-module/src/main/java/my/test/resource/Foo.java new file mode 100644 index 0000000..8074ce8 --- /dev/null +++ b/jwo-test-module/src/main/java/my/test/resource/Foo.java @@ -0,0 +1,4 @@ +package my.test.resource; + +public class Foo { +} diff --git a/jwo-test-module/src/main/resources/my/test/resource/file.txt b/jwo-test-module/src/main/resources/my/test/resource/file.txt new file mode 100644 index 0000000..30d74d2 --- /dev/null +++ b/jwo-test-module/src/main/resources/my/test/resource/file.txt @@ -0,0 +1 @@ +test \ No newline at end of file diff --git a/jwo-test/build.gradle b/jwo-test/build.gradle new file mode 100644 index 0000000..fc17e03 --- /dev/null +++ b/jwo-test/build.gradle @@ -0,0 +1,31 @@ +plugins { + id 'java-library' + alias(catalog.plugins.lombok) +} + +import org.gradle.api.attributes.LibraryElements +import static org.gradle.api.attributes.LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE +import static org.gradle.api.attributes.LibraryElements.JAR + +configurations { + testImplementation { + attributes { + attribute(LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.class, JAR)) + } + } + + testRuntimeClasspath { + attributes { + attribute(LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.class, JAR)) + } + } +} + +java { + modularity.inferModulePath = true +} + +dependencies { + testImplementation project(':jwo-test-module') + testImplementation project(':') +} \ No newline at end of file diff --git a/jwo-test/src/test/java/module-info.java b/jwo-test/src/test/java/module-info.java new file mode 100644 index 0000000..675bae8 --- /dev/null +++ b/jwo-test/src/test/java/module-info.java @@ -0,0 +1,6 @@ +open module net.woggioni.jwo.unit.test { + requires net.woggioni.jwo; + requires net.woggioni.jwo.test.module; + requires org.junit.jupiter.api; + requires static lombok; +} \ No newline at end of file diff --git a/jwo-test/src/test/java/net/woggioni/jwo/test/JpmsUrlTest.java b/jwo-test/src/test/java/net/woggioni/jwo/test/JpmsUrlTest.java new file mode 100644 index 0000000..43e5865 --- /dev/null +++ b/jwo-test/src/test/java/net/woggioni/jwo/test/JpmsUrlTest.java @@ -0,0 +1,29 @@ +package net.woggioni.jwo.test; + +import lombok.SneakyThrows; +import net.woggioni.jwo.JWO; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayOutputStream; +import java.net.URL; +import java.nio.charset.StandardCharsets; + +public class JpmsUrlTest { + @Test + @SneakyThrows + public void test() { + JWO.registerUrlProtocolHandler(); + final var module = getClass().getModule(); + final var url = new URL("jpms://net.woggioni.jwo.test.module/my/test/resource/file.txt"); + System.out.println(module.getName()); + System.out.println(url.getHost()); + System.out.println(url.getPath()); + final var baos = new ByteArrayOutputStream(); + try(final var is = url.openConnection().getInputStream()) { + JWO.copy(is, baos); + } + final var content = baos.toString(StandardCharsets.UTF_8); + Assertions.assertEquals("test", content); + } +} diff --git a/settings.gradle b/settings.gradle index 43b237d..8aa3053 100644 --- a/settings.gradle +++ b/settings.gradle @@ -25,6 +25,8 @@ dependencyResolutionManagement { rootProject.name = 'jwo' -include('benchmark') -include('jmath') -include('jmath-benchmark') +include 'benchmark' +include 'jmath' +include 'jmath-benchmark' +include 'jwo-test' +include 'jwo-test-module' \ No newline at end of file diff --git a/src/main/java/net/woggioni/jwo/UncloseableOutputStream.java b/src/main/java/net/woggioni/jwo/UncloseableOutputStream.java index 13fa55b..1a28b77 100644 --- a/src/main/java/net/woggioni/jwo/UncloseableOutputStream.java +++ b/src/main/java/net/woggioni/jwo/UncloseableOutputStream.java @@ -1,6 +1,7 @@ package net.woggioni.jwo; import java.io.FilterOutputStream; +import java.io.IOException; import java.io.OutputStream; /** @@ -14,6 +15,7 @@ public class UncloseableOutputStream extends FilterOutputStream { } @Override - public void close() { + public void close() throws IOException { + flush(); } } diff --git a/src/main/java/net/woggioni/jwo/UncloseableWriter.java b/src/main/java/net/woggioni/jwo/UncloseableWriter.java index 0a74d53..b62eab5 100644 --- a/src/main/java/net/woggioni/jwo/UncloseableWriter.java +++ b/src/main/java/net/woggioni/jwo/UncloseableWriter.java @@ -10,5 +10,7 @@ public class UncloseableWriter extends FilterWriter { } @Override - public void close() throws IOException {} + public void close() throws IOException { + flush(); + } } \ No newline at end of file diff --git a/src/main/java9/module-info.java b/src/main/java9/module-info.java index 5191282..14a57d1 100644 --- a/src/main/java9/module-info.java +++ b/src/main/java9/module-info.java @@ -7,5 +7,6 @@ module net.woggioni.jwo { exports net.woggioni.jwo; exports net.woggioni.jwo.exception; exports net.woggioni.jwo.url.classpath; + exports net.woggioni.jwo.url.jpms; exports net.woggioni.jwo.xml; } \ No newline at end of file diff --git a/src/main/java9/net/woggioni/jwo/url/jpms/Handler.java b/src/main/java9/net/woggioni/jwo/url/jpms/Handler.java new file mode 100644 index 0000000..4c6ed2d --- /dev/null +++ b/src/main/java9/net/woggioni/jwo/url/jpms/Handler.java @@ -0,0 +1,52 @@ +package net.woggioni.jwo.url.jpms; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.Module; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; +import java.util.Optional; + +public class Handler extends URLStreamHandler { + private final ClassLoader classLoader; + + public Handler() { + this.classLoader = getClass().getClassLoader(); + } + + public Handler(ClassLoader classLoader) { + this.classLoader = classLoader; + } + + @Override + protected URLConnection openConnection(URL u) throws IOException { + final Module thisModule = getClass().getModule(); + final Module sourceModule = Optional.ofNullable(thisModule) + .map(Module::getLayer) + .flatMap(layer -> { + final String moduleName = u.getHost(); + return layer.findModule(moduleName); + }).orElse(thisModule); + return new ModuleResourceURLConnection(u, sourceModule); + } + + private static class ModuleResourceURLConnection extends URLConnection { + private final Module module; + + private ModuleResourceURLConnection(URL url, Module module) { + super(url); + this.module = module; + } + + @Override + public void connect() { + + } + + @Override + public InputStream getInputStream() throws IOException { + return module.getResourceAsStream(getURL().getPath()); + } + } +} diff --git a/src/test/java/net/woggioni/jwo/url/JpmsUrlTest.java b/src/test/java/net/woggioni/jwo/url/JpmsUrlTest.java new file mode 100644 index 0000000..7123c7e --- /dev/null +++ b/src/test/java/net/woggioni/jwo/url/JpmsUrlTest.java @@ -0,0 +1,26 @@ +package net.woggioni.jwo.url; + +import lombok.SneakyThrows; +import net.woggioni.jwo.JWO; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayOutputStream; +import java.net.URL; +import java.nio.charset.StandardCharsets; + +public class JpmsUrlTest { + @Test + @SneakyThrows + public void test() { + JWO.registerUrlProtocolHandler(); + final var module = getClass().getModule(); + final var url = new URL("jpms://net.woggioni.jwo.test.module/my/test/resource/file.txt"); + final var baos = new ByteArrayOutputStream(); + try(final var is = url.openConnection().getInputStream()) { + JWO.copy(is, baos); + } + final var content = baos.toString(StandardCharsets.UTF_8); + Assertions.assertEquals("test", content); + } +}