diff --git a/build.gradle b/build.gradle index b0116f5..a9defb6 100644 --- a/build.gradle +++ b/build.gradle @@ -13,12 +13,21 @@ allprojects { repositories { maven { url = woggioniMavenRepositoryUrl + content { + includeModule 'net.woggioni', 'xclassloader' + } } mavenCentral() } group = "net.woggioni.gradle" + java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } + } + lombok { version = getProperty('version.lombok') } @@ -33,6 +42,10 @@ allprojects { add("testImplementation", gradleTestKit()) } + tasks.named(JavaPlugin.COMPILE_JAVA_TASK_NAME, JavaCompile) { + options.release = 8 + } + tasks.named("test", Test) { useJUnitPlatform() } @@ -58,11 +71,6 @@ dependencies { embedded project(path: "common", configuration: "archives") } -java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 -} - tasks.named('processResources', ProcessResources) { from { configurations.named('embedded').map { diff --git a/common/build.gradle b/common/build.gradle index dced01e..2e6880d 100644 --- a/common/build.gradle +++ b/common/build.gradle @@ -1,8 +1,3 @@ -java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 -} - jar { manifest { attributes "Automatic-Module-Name" : "net.woggioni.envelope" diff --git a/gradle.properties b/gradle.properties index 4a2d429..942af9d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,8 +1,10 @@ woggioniMavenRepositoryUrl=https://woggioni.net/mvn/ publishMavenRepositoryUrl=https://mvn.woggioni.net/ -version.envelope=1.0-SNAPSHOT -version.gradle=7.4 +lys-gradle-plugins.version = 2022.06 + +version.envelope=2022.06 +version.gradle=7.4.2 version.lombok=1.18.22 version.xclassloader=1.0-SNAPSHOT version.junitJupiter=5.7.2 diff --git a/launcher/build.gradle b/launcher/build.gradle index 686bfb2..7bb831b 100644 --- a/launcher/build.gradle +++ b/launcher/build.gradle @@ -1,10 +1,11 @@ import java.util.jar.Attributes - plugins { - id "net.woggioni.gradle.multi-release-jar" + id 'net.woggioni.gradle.multi-release-jar' } -ext.setProperty("jpms.module.name", "net.woggioni.envelope") +ext { + setProperty('jpms.module.name', 'net.woggioni.envelope') +} configurations { embedded { @@ -28,18 +29,11 @@ java { modularity.inferModulePath = true } -tasks.withType(JavaCompile).configureEach { - javaCompiler = javaToolchains.compilerFor { - languageVersion = JavaLanguageVersion.of(16) - } - options.forkOptions.jvmArgs << "--illegal-access=permit" -} - jar { manifest { attributes([ - (Attributes.Name.SPECIFICATION_TITLE) : "envelope-launcher", - (Attributes.Name.SEALED) : true + (Attributes.Name.SPECIFICATION_TITLE) : "envelope-launcher", + (Attributes.Name.SEALED) : true ].collectEntries { [it.key.toString(), it.value.toString()] }) @@ -62,13 +56,6 @@ Provider tarTaskProvider = tasks.register("tar", Tar) { } } -tasks.named(JavaPlugin.COMPILE_JAVA_TASK_NAME, JavaCompile) { - doFirst { - String path = project(":common").extensions.getByType(JavaPluginExtension).sourceSets.named("main").get().output.asPath - options.compilerArgs.addAll(["--patch-module", "net.woggioni.envelope=$path"]) - } -} - artifacts { tar tarTaskProvider } \ No newline at end of file diff --git a/launcher/src/main/java11/module-info.java b/launcher/src/java11/java/module-info.java similarity index 100% rename from launcher/src/main/java11/module-info.java rename to launcher/src/java11/java/module-info.java diff --git a/launcher/src/java11/java/net/woggioni/envelope/MainRunner.java b/launcher/src/java11/java/net/woggioni/envelope/MainRunner.java new file mode 100644 index 0000000..7317629 --- /dev/null +++ b/launcher/src/java11/java/net/woggioni/envelope/MainRunner.java @@ -0,0 +1,86 @@ +package net.woggioni.envelope; + +import java.util.Map; +import java.util.TreeMap; +import java.lang.module.Configuration; +import java.lang.module.ModuleFinder; +import java.lang.module.ResolvedModule; +import java.lang.module.ModuleReference; +import java.util.Collections; +import java.util.List; +import java.util.ArrayList; +import java.util.Optional; +import java.util.Enumeration; +import java.util.function.Consumer; +import java.net.URL; +import java.net.URLClassLoader; + + +import lombok.SneakyThrows; + +import net.woggioni.xclassloader.ModuleClassLoader; +import net.woggioni.xclassloader.JarFileModuleFinder; +import net.woggioni.xclassloader.jar.JarFile; +import java.util.jar.JarEntry; + +class MainRunner { + + @SneakyThrows + static void run(JarFile currentJarFile, + String mainModuleName, + String mainClassName, + String librariesFolder, + Consumer> runner) { + if(mainModuleName == null) { + List jarList = new ArrayList<>(); + Enumeration entries = currentJarFile.entries(); + while(entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + String name = entry.getName(); + if(!entry.isDirectory() && name.startsWith(librariesFolder) && name.endsWith(".jar")) { + jarList.add(currentJarFile.getNestedJarFile(entry).getUrl()); + } + } + try (URLClassLoader cl = new URLClassLoader(jarList.toArray(new URL[0]), ClassLoader.getSystemClassLoader().getParent())) { + Thread.currentThread().setContextClassLoader(cl); + runner.accept(cl.loadClass(mainClassName)); + } + } else { + List jarList = new ArrayList<>(); + Enumeration entries = currentJarFile.entries(); + while(entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + String name = entry.getName(); + if(!entry.isDirectory() && name.startsWith("LIB-INF") && name.endsWith(".jar")) { + jarList.add(currentJarFile.getNestedJarFile(entry)); + } + } + ModuleLayer bootLayer = ModuleLayer.boot(); + Configuration bootConfiguration = bootLayer.configuration(); + Configuration cfg = bootConfiguration.resolve(new JarFileModuleFinder(jarList), ModuleFinder.of(), Collections.singletonList(mainModuleName)); + Map packageMap = new TreeMap<>(); + ModuleLayer.Controller controller = + ModuleLayer.defineModules(cfg, Collections.singletonList(ModuleLayer.boot()), moduleName -> { + ModuleReference modRef = cfg.findModule(moduleName) + .map(ResolvedModule::reference) + .orElseThrow(); + ClassLoader cl = new ModuleClassLoader( + Collections.unmodifiableMap(packageMap), + modRef + ); + for(String packageName : modRef.descriptor().packages()) { + packageMap.put(packageName, cl); + } + return cl; + }); + ModuleLayer layer = controller.layer(); + Module mainModule = layer.findModule(mainModuleName).orElseThrow( + () -> new IllegalStateException(String.format("Main module '%s' not found", mainModuleName))); + runner.accept(Optional.ofNullable(mainClassName) + .or(() -> mainModule.getDescriptor().mainClass()) + .map(className -> Class.forName(mainModule, className)) + .orElseThrow(() -> new IllegalStateException( + String.format("Unable to determine main class name for module '%s'", mainModule.getName())))); + } + } +} diff --git a/launcher/src/main/java/net/woggioni/envelope/Launcher.java b/launcher/src/main/java/net/woggioni/envelope/Launcher.java index b3a6d3f..ad24a9d 100644 --- a/launcher/src/main/java/net/woggioni/envelope/Launcher.java +++ b/launcher/src/main/java/net/woggioni/envelope/Launcher.java @@ -1,44 +1,49 @@ package net.woggioni.envelope; import lombok.SneakyThrows; -import net.woggioni.xclassloader.PathURLStreamHandler; -import net.woggioni.xclassloader.URLManager; +import net.woggioni.xclassloader.jar.JarFile; +import java.io.File; import java.io.InputStream; import java.lang.reflect.Method; import java.net.URI; import java.net.URL; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Collections; import java.util.Enumeration; -import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Properties; -import java.util.function.Function; +import java.util.function.Consumer; import java.util.jar.Attributes; -import java.util.jar.JarFile; import java.util.jar.Manifest; -import java.util.stream.Collector; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; +import static java.util.jar.JarFile.MANIFEST_NAME; public class Launcher { @SneakyThrows - private static URI findCurrentJar() { + private static JarFile findCurrentJar() { String launcherClassName = Launcher.class.getName(); URL url = Launcher.class.getClassLoader().getResource(launcherClassName.replace('.', '/') + ".class"); if (url == null || !"jar".equals(url.getProtocol())) throw new IllegalStateException(String.format("The class %s must be used inside a JAR file", launcherClassName)); - String path = url.getPath(); - return new URI(path.substring(0, path.indexOf('!'))); + String path = Paths.get(new URI(url.getPath())).toString(); + return new JarFile(new File(path.substring(0, path.indexOf('!')))); + } + + @SneakyThrows + private static void run(Class mainClass, String[] args) { + try { + Method mainMethod = mainClass.getMethod("main", String[].class); + Class returnType = mainMethod.getReturnType(); + if (mainMethod.getReturnType() != Void.TYPE) { + throw new IllegalArgumentException(String.format("Main method in class '%s' " + + "has wrong return type, expected '%s', found '%s' instead", mainClass, Void.class.getName(), returnType)); + } + mainMethod.invoke(null, (Object) args); + } catch (NoSuchMethodException nsme) { + throw new IllegalArgumentException(String.format("No valid main method found in class '%s'", mainClass), nsme); + } } @SneakyThrows @@ -53,69 +58,58 @@ public class Launcher { for (Map.Entry entry : properties.entrySet()) { String key = (String) entry.getKey(); String value = (String) entry.getValue(); - if(System.getProperty(key) == null) System.setProperty(key, value); + if (System.getProperty(key) == null) System.setProperty(key, value); } } - URI currentJar = findCurrentJar(); - String currentJarPath = currentJar.getPath(); + JarFile currentJar = findCurrentJar(); URL manifestResource = null; - Enumeration enumeration = Launcher.class.getClassLoader().getResources(JarFile.MANIFEST_NAME); - while(enumeration.hasMoreElements()) { + Enumeration enumeration = Launcher.class.getClassLoader().getResources(MANIFEST_NAME); + while (enumeration.hasMoreElements()) { URL candidate = enumeration.nextElement(); URL subUrl = new URL(candidate.getFile()); String candidatePath = subUrl.getPath(); int i = candidatePath.indexOf("!/"); candidatePath = candidatePath.substring(0, i); - if(Objects.equals(currentJarPath, candidatePath)) { + if (Objects.equals(currentJar.getName(), candidatePath)) { manifestResource = candidate; break; } } - if(Objects.isNull(manifestResource)) { + if (Objects.isNull(manifestResource)) { throw new RuntimeException("Launcher manifest not found"); } Manifest mf = new Manifest(); - try(InputStream is = manifestResource.openStream()) { + try (InputStream is = manifestResource.openStream()) { mf.read(is); } - try(FileSystem fs = FileSystems.newFileSystem(Paths.get(currentJar), null)) { - Attributes mainAttributes = mf.getMainAttributes(); + Attributes mainAttributes = mf.getMainAttributes(); - Collector, List> immutableListCollector = Collector.of( - ArrayList::new, - List::add, - (l1, l2) -> { l1.addAll(l2); return l1; }, - Collections::unmodifiableList); - List jarList = StreamSupport.stream(fs.getRootDirectories().spliterator(), false).flatMap(new Function>() { - @Override - @SneakyThrows - public Stream apply(Path path) { - return Files.list(path.resolve(Constants.LIBRARIES_FOLDER)) - .filter(Files::isRegularFile) - .filter(p -> p.getFileName().toString().endsWith(".jar")); - } - }).flatMap(new Function>() { - @Override - @SneakyThrows - public Stream apply(Path path) { - return StreamSupport.stream(FileSystems.newFileSystem(path, null).getRootDirectories().spliterator(), false); - } - }).collect(immutableListCollector); + String mainClassName = mainAttributes.getValue(Constants.ManifestAttributes.MAIN_CLASS); + String mainModuleName = mainAttributes.getValue(Constants.ManifestAttributes.MAIN_MODULE); - String mainClassName = mainAttributes.getValue(Constants.ManifestAttributes.MAIN_CLASS); - String mainModuleName = mainAttributes.getValue(Constants.ManifestAttributes.MAIN_MODULE); - Class mainClass = MainClassLoader.loadMainClass(jarList, mainModuleName, mainClassName); - try { - Method mainMethod = mainClass.getMethod("main", String[].class); - Class returnType = mainMethod.getReturnType(); - if (mainMethod.getReturnType() != Void.TYPE) { - throw new IllegalArgumentException(String.format("Main method in class '%s' " + - "has wrong return type, expected '%s', found '%s' instead", mainClass, Void.class.getName(), returnType)); + Consumer> runner = new Consumer>() { + @Override + @SneakyThrows + public void accept(Class mainClass) { + try { + Method mainMethod = mainClass.getMethod("main", String[].class); + Class returnType = mainMethod.getReturnType(); + if (mainMethod.getReturnType() != Void.TYPE) { + throw new IllegalArgumentException(String.format("Main method in class '%s' " + + "has wrong return type, expected '%s', found '%s' instead", mainClass, Void.class.getName(), returnType)); + } + mainMethod.invoke(null, (Object) args); + } catch (NoSuchMethodException nsme) { + throw new IllegalArgumentException(String.format("No valid main method found in class '%s'", mainClass), nsme); } - mainMethod.invoke(null, (Object) args); - } catch (NoSuchMethodException nsme) { - throw new IllegalArgumentException(String.format("No valid main method found in class '%s'", mainClass), nsme); } - } + }; + MainRunner.run( + currentJar, + mainModuleName, + mainClassName, + Constants.LIBRARIES_FOLDER, + runner); + } } diff --git a/launcher/src/main/java/net/woggioni/envelope/MainClassLoader.java b/launcher/src/main/java/net/woggioni/envelope/MainClassLoader.java deleted file mode 100644 index 97e7ce9..0000000 --- a/launcher/src/main/java/net/woggioni/envelope/MainClassLoader.java +++ /dev/null @@ -1,13 +0,0 @@ -package net.woggioni.envelope; - -import java.nio.file.Path; -import lombok.SneakyThrows; - -class MainClassLoader { - @SneakyThrows - static Class loadMainClass(Iterable roots, String mainModuleName, String mainClassName) { - ClassLoader pathClassLoader = new net.woggioni.xclassloader.PathClassLoader(roots, ClassLoader.getSystemClassLoader().getParent()); - Thread.currentThread().setContextClassLoader(pathClassLoader); - return pathClassLoader.loadClass(mainClassName); - } -} diff --git a/launcher/src/main/java/net/woggioni/envelope/MainRunner.java b/launcher/src/main/java/net/woggioni/envelope/MainRunner.java new file mode 100644 index 0000000..065cfd4 --- /dev/null +++ b/launcher/src/main/java/net/woggioni/envelope/MainRunner.java @@ -0,0 +1,35 @@ +package net.woggioni.envelope; + +import lombok.SneakyThrows; +import net.woggioni.xclassloader.jar.JarFile; + +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; +import java.util.function.Consumer; +import java.util.jar.JarEntry; + +class MainRunner { + @SneakyThrows + static void run(JarFile currentJarFile, + String mainModuleName, + String mainClassName, + String librariesFolder, + Consumer> runner) { + List jarList = new ArrayList<>(); + Enumeration entries = currentJarFile.entries(); + while(entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + String name = entry.getName(); + if(!entry.isDirectory() && name.startsWith(librariesFolder) && name.endsWith(".jar")) { + jarList.add(currentJarFile.getNestedJarFile(entry).getUrl()); + } + } + try (URLClassLoader cl = new URLClassLoader(jarList.toArray(new URL[0]), ClassLoader.getSystemClassLoader().getParent())) { + Thread.currentThread().setContextClassLoader(cl); + runner.accept(cl.loadClass(mainClassName)); + } + } +} diff --git a/launcher/src/main/java11/net/woggioni/envelope/MainClassLoader.java b/launcher/src/main/java11/net/woggioni/envelope/MainClassLoader.java deleted file mode 100644 index 5d99e50..0000000 --- a/launcher/src/main/java11/net/woggioni/envelope/MainClassLoader.java +++ /dev/null @@ -1,55 +0,0 @@ -package net.woggioni.envelope; - -import java.util.Map; -import java.util.TreeMap; -import java.lang.module.Configuration; -import java.lang.module.ModuleFinder; -import java.lang.module.ResolvedModule; -import java.lang.module.ModuleReference; -import java.nio.file.Path; -import java.util.Collections; -import java.util.Optional; - -import lombok.SneakyThrows; - -import net.woggioni.xclassloader.PathClassLoader; -import net.woggioni.xclassloader.ModuleClassLoader; -import net.woggioni.xclassloader.PathModuleFinder; - -class MainClassLoader { - - @SneakyThrows - static Class loadMainClass(Iterable roots, String mainModuleName, String mainClassName) { - if (mainModuleName == null) { - ClassLoader pathClassLoader = new net.woggioni.xclassloader.PathClassLoader(roots, ClassLoader.getSystemClassLoader().getParent()); - Thread.currentThread().setContextClassLoader(pathClassLoader); - return pathClassLoader.loadClass(mainClassName); - } else { - ModuleLayer bootLayer = ModuleLayer.boot(); - Configuration bootConfiguration = bootLayer.configuration(); - Configuration cfg = bootConfiguration.resolve(new PathModuleFinder(roots), ModuleFinder.of(), Collections.singletonList(mainModuleName)); - Map packageMap = new TreeMap<>(); - ModuleLayer.Controller controller = - ModuleLayer.defineModules(cfg, Collections.singletonList(ModuleLayer.boot()), moduleName -> { - ModuleReference modRef = cfg.findModule(moduleName) - .map(ResolvedModule::reference) - .orElseThrow(); - ClassLoader cl = new ModuleClassLoader( - Collections.unmodifiableMap(packageMap), - modRef - ); - for(String packageName : modRef.descriptor().packages()) { - packageMap.put(packageName, cl); - } - return cl; - }); - ModuleLayer layer = controller.layer(); - Module mainModule = layer.findModule(mainModuleName).orElseThrow( - () -> new IllegalStateException(String.format("Main module '%s' not found", mainModuleName))); - return Optional.ofNullable(mainClassName) - .or(() -> mainModule.getDescriptor().mainClass()) - .map(className -> Class.forName(mainModule, className)) - .orElseThrow(() -> new IllegalStateException(String.format("Unable to determine main class name for module '%s'", mainModule.getName()))); - } - } -} diff --git a/launcher/src/main/java11/net/woggioni/envelope/MainRunner.java b/launcher/src/main/java11/net/woggioni/envelope/MainRunner.java new file mode 100644 index 0000000..7317629 --- /dev/null +++ b/launcher/src/main/java11/net/woggioni/envelope/MainRunner.java @@ -0,0 +1,86 @@ +package net.woggioni.envelope; + +import java.util.Map; +import java.util.TreeMap; +import java.lang.module.Configuration; +import java.lang.module.ModuleFinder; +import java.lang.module.ResolvedModule; +import java.lang.module.ModuleReference; +import java.util.Collections; +import java.util.List; +import java.util.ArrayList; +import java.util.Optional; +import java.util.Enumeration; +import java.util.function.Consumer; +import java.net.URL; +import java.net.URLClassLoader; + + +import lombok.SneakyThrows; + +import net.woggioni.xclassloader.ModuleClassLoader; +import net.woggioni.xclassloader.JarFileModuleFinder; +import net.woggioni.xclassloader.jar.JarFile; +import java.util.jar.JarEntry; + +class MainRunner { + + @SneakyThrows + static void run(JarFile currentJarFile, + String mainModuleName, + String mainClassName, + String librariesFolder, + Consumer> runner) { + if(mainModuleName == null) { + List jarList = new ArrayList<>(); + Enumeration entries = currentJarFile.entries(); + while(entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + String name = entry.getName(); + if(!entry.isDirectory() && name.startsWith(librariesFolder) && name.endsWith(".jar")) { + jarList.add(currentJarFile.getNestedJarFile(entry).getUrl()); + } + } + try (URLClassLoader cl = new URLClassLoader(jarList.toArray(new URL[0]), ClassLoader.getSystemClassLoader().getParent())) { + Thread.currentThread().setContextClassLoader(cl); + runner.accept(cl.loadClass(mainClassName)); + } + } else { + List jarList = new ArrayList<>(); + Enumeration entries = currentJarFile.entries(); + while(entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + String name = entry.getName(); + if(!entry.isDirectory() && name.startsWith("LIB-INF") && name.endsWith(".jar")) { + jarList.add(currentJarFile.getNestedJarFile(entry)); + } + } + ModuleLayer bootLayer = ModuleLayer.boot(); + Configuration bootConfiguration = bootLayer.configuration(); + Configuration cfg = bootConfiguration.resolve(new JarFileModuleFinder(jarList), ModuleFinder.of(), Collections.singletonList(mainModuleName)); + Map packageMap = new TreeMap<>(); + ModuleLayer.Controller controller = + ModuleLayer.defineModules(cfg, Collections.singletonList(ModuleLayer.boot()), moduleName -> { + ModuleReference modRef = cfg.findModule(moduleName) + .map(ResolvedModule::reference) + .orElseThrow(); + ClassLoader cl = new ModuleClassLoader( + Collections.unmodifiableMap(packageMap), + modRef + ); + for(String packageName : modRef.descriptor().packages()) { + packageMap.put(packageName, cl); + } + return cl; + }); + ModuleLayer layer = controller.layer(); + Module mainModule = layer.findModule(mainModuleName).orElseThrow( + () -> new IllegalStateException(String.format("Main module '%s' not found", mainModuleName))); + runner.accept(Optional.ofNullable(mainClassName) + .or(() -> mainModule.getDescriptor().mainClass()) + .map(className -> Class.forName(mainModule, className)) + .orElseThrow(() -> new IllegalStateException( + String.format("Unable to determine main class name for module '%s'", mainModule.getName())))); + } + } +} diff --git a/settings.gradle b/settings.gradle index c16eea8..3daaa20 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,6 +4,8 @@ pluginManagement { content { includeModule 'net.woggioni.gradle', 'lombok' includeModule 'net.woggioni.gradle.lombok', 'net.woggioni.gradle.lombok.gradle.plugin' + includeModule 'net.woggioni.gradle', 'multi-version-jar' + includeModule 'net.woggioni.gradle.multi-version-jar', 'net.woggioni.gradle.multi-version-jar.gradle.plugin' includeModule 'net.woggioni.gradle', 'multi-release-jar' includeModule 'net.woggioni.gradle.multi-release-jar', 'net.woggioni.gradle.multi-release-jar.gradle.plugin' } @@ -12,8 +14,9 @@ pluginManagement { } plugins { - id 'net.woggioni.gradle.lombok' version "0.1" - id "net.woggioni.gradle.multi-release-jar" version "0.1" + id 'net.woggioni.gradle.lombok' version getProperty('lys-gradle-plugins.version') + id 'net.woggioni.gradle.multi-version-jar' version getProperty('lys-gradle-plugins.version') + id 'net.woggioni.gradle.multi-release-jar' version getProperty('lys-gradle-plugins.version') } } diff --git a/src/main/java/net/woggioni/gradle/envelope/EnvelopeJarTask.java b/src/main/java/net/woggioni/gradle/envelope/EnvelopeJarTask.java index bdb8b2f..731dd77 100644 --- a/src/main/java/net/woggioni/gradle/envelope/EnvelopeJarTask.java +++ b/src/main/java/net/woggioni/gradle/envelope/EnvelopeJarTask.java @@ -220,7 +220,7 @@ public class EnvelopeJarTask extends AbstractArchiveTask { Attributes mainAttributes = manifest.getMainAttributes(); mainAttributes.put(Attributes.Name.MANIFEST_VERSION, "1.0"); mainAttributes.put(Attributes.Name.MAIN_CLASS, Constants.DEFAULT_LAUNCHER); - mainAttributes.put(Attributes.Name.MULTI_RELEASE, "true"); + mainAttributes.putValue("Multi-Release", "true"); mainAttributes.put(new Attributes.Name("Launcher-Agent-Class"), Constants.AGENT_LAUNCHER); mainAttributes.put(new Attributes.Name("Can-Redefine-Classes"), "true"); mainAttributes.put(new Attributes.Name("Can-Retransform-Classes"), "true"); diff --git a/src/test/java/net/woggioni/gradle/envelope/test/EnvelopePluginTest.java b/src/test/java/net/woggioni/gradle/envelope/test/EnvelopePluginTest.java index 39cc9f8..aac4ee7 100644 --- a/src/test/java/net/woggioni/gradle/envelope/test/EnvelopePluginTest.java +++ b/src/test/java/net/woggioni/gradle/envelope/test/EnvelopePluginTest.java @@ -28,6 +28,7 @@ import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import org.junit.jupiter.api.Assertions; + import static java.util.concurrent.TimeUnit.MINUTES; public class EnvelopePluginTest { @@ -44,15 +45,15 @@ public class EnvelopePluginTest { return getResource(resourceName, cls, null); } - private static URL getResource(String resourceName, Class cls, ClassLoader cl) { + private static URL getResource(String resourceName, Class cls, ClassLoader cl) { URL result = null; - if(cl != null) { + if (cl != null) { result = cl.getResource(resourceName); } - if(result == null && cls != null) { + if (result == null && cls != null) { result = cls.getClassLoader().getResource(resourceName); } - if(result == null) { + if (result == null) { result = EnvelopePluginTest.class.getClassLoader().getResource(resourceName); } return result; @@ -90,10 +91,11 @@ public class EnvelopePluginTest { GradleRunner runner = GradleRunner.create() .withDebug(true) .withProjectDir(rootProjectDir.toFile()) - .withArguments(Arrays.concat(new String[] {"-s", "--info", "-g", testGradleHomeDir.toString()}, taskName)) + .withArguments(Arrays.concat(new String[]{"-s", "--info", "-g", testGradleHomeDir.toString()}, taskName)) .withPluginClasspath(); System.out.println(runner.build().getOutput()); } + private Path testDir; private static final Path testGradleHomeDir = Paths.get(System.getProperty("test.gradle.user.home")); @@ -102,14 +104,14 @@ public class EnvelopePluginTest { public void setup(@TempDir Path testDir) { this.testDir = testDir; String resourceFile = "test-resources.txt"; - try(BufferedReader reader = - Optional.ofNullable(getResource(resourceFile).openStream()) - .map(InputStreamReader::new) - .map(BufferedReader::new) - .orElseThrow(() -> new FileNotFoundException(resourceFile))) { - while(true) { + try (BufferedReader reader = + Optional.ofNullable(getResource(resourceFile).openStream()) + .map(InputStreamReader::new) + .map(BufferedReader::new) + .orElseThrow(() -> new FileNotFoundException(resourceFile))) { + while (true) { String line = reader.readLine(); - if(line == null) break; + if (line == null) break; Path destination = testDir.resolve(line); Files.createDirectories(destination.getParent()); Files.copy(getResource(line).openStream(), destination); @@ -123,7 +125,7 @@ public class EnvelopePluginTest { } @Test - void jpmsTest() { + void jpmsTest() { invokeGradle(testDir.resolve("test-project"), ":jpms-executable:envelopeRun"); }