From da86fcc6ce84c6dcdf6062cf364abff881e236e0 Mon Sep 17 00:00:00 2001 From: Tako Schotanus Date: Thu, 8 Jun 2023 17:22:56 +0200 Subject: [PATCH 1/5] chore: fixed formatting issue --- src/test/java/dev/jbang/cli/TestJdk.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/java/dev/jbang/cli/TestJdk.java b/src/test/java/dev/jbang/cli/TestJdk.java index f7147657b..b2efc58df 100644 --- a/src/test/java/dev/jbang/cli/TestJdk.java +++ b/src/test/java/dev/jbang/cli/TestJdk.java @@ -14,7 +14,6 @@ import java.nio.file.Path; import java.util.Arrays; import java.util.function.BiConsumer; -import java.util.function.BiFunction; import java.util.function.Function; import org.junit.jupiter.api.BeforeEach; @@ -442,7 +441,6 @@ private void createMockJdk(int jdkVersion, BiConsumer init) { } } - private void initMockJdkDirRuntime(Path jdkPath, String version) { initMockJdkDir(jdkPath, version, "JAVA_RUNTIME_VERSION"); } @@ -450,6 +448,7 @@ private void initMockJdkDirRuntime(Path jdkPath, String version) { private void initMockJdkDir(Path jdkPath, String version) { initMockJdkDir(jdkPath, version, "JAVA_VERSION"); } + private void initMockJdkDir(Path jdkPath, String version, String key) { Util.mkdirs(jdkPath); String rawJavaVersion = key + "=\"" + version + "\""; From 5b263bfa172d4456c677f7cf5eca021ea7d12b80 Mon Sep 17 00:00:00 2001 From: Tako Schotanus Date: Wed, 7 Jun 2023 17:35:34 +0200 Subject: [PATCH 2/5] fix: Now showing integration errors when verbose is on Fixes #1499 --- src/main/java/dev/jbang/spi/IntegrationInput.java | 4 +++- src/main/java/dev/jbang/spi/IntegrationManager.java | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/dev/jbang/spi/IntegrationInput.java b/src/main/java/dev/jbang/spi/IntegrationInput.java index 840fa0e5d..de94a2494 100644 --- a/src/main/java/dev/jbang/spi/IntegrationInput.java +++ b/src/main/java/dev/jbang/spi/IntegrationInput.java @@ -17,10 +17,11 @@ public class IntegrationInput { public final List comments; @SerializedName(value = "native") public final boolean nativeRequested; + public final boolean verbose; public IntegrationInput(String integrationClassName, Path source, Path classes, Path pom, Map repositories, Map dependencies, List comments, - boolean nativeRequested) { + boolean nativeRequested, boolean verbose) { this.integrationClassName = integrationClassName; this.source = source; this.classes = classes; @@ -29,5 +30,6 @@ public IntegrationInput(String integrationClassName, Path source, Path classes, this.dependencies = dependencies; this.comments = comments; this.nativeRequested = nativeRequested; + this.verbose = verbose; } } diff --git a/src/main/java/dev/jbang/spi/IntegrationManager.java b/src/main/java/dev/jbang/spi/IntegrationManager.java index 461eb9d61..75b8c993d 100644 --- a/src/main/java/dev/jbang/spi/IntegrationManager.java +++ b/src/main/java/dev/jbang/spi/IntegrationManager.java @@ -87,8 +87,7 @@ public static IntegrationResult runIntegrations(Project prj, Path tmpJarDir, Pat ? source.getResourceRef().getFile().toAbsolutePath() : null; IntegrationInput input = new IntegrationInput(className, srcPath, tmpJarDir, pomPath, repos, deps, - comments, - prj.isNativeImage()); + comments, prj.isNativeImage(), Util.isVerbose()); IntegrationResult ir = requestedJavaVersion == null || JavaUtil.satisfiesRequestedVersion( requestedJavaVersion, JavaUtil.getCurrentMajorJavaVersion()) ? runIntegrationEmbedded(input, integrationCl) @@ -267,6 +266,7 @@ public static void main(String... args) { IntegrationInput input = parser.fromJson(new InputStreamReader(System.in), IntegrationInput.class); ClassLoader old = Thread.currentThread().getContextClassLoader(); PrintStream oldout = System.out; + Util.setVerbose(input.verbose); String output = ""; boolean ok = false; try { @@ -281,6 +281,9 @@ public static void main(String... args) { output = "Integration class missing method with signature public static Map postBuild(Path classesDir, Path pomFile, List> dependencies)"; } catch (Exception e) { output = "Issue running postBuild()"; + if (input.verbose) { + e.printStackTrace(System.err); + } } finally { Thread.currentThread().setContextClassLoader(old); System.setOut(oldout); From 8e14b367523f878ffb7451d44aa74814ff9dc810 Mon Sep 17 00:00:00 2001 From: Tako Schotanus Date: Wed, 7 Jun 2023 17:41:50 +0200 Subject: [PATCH 3/5] fix: External integrations will now work in IDE Before the class loader would not be set up correctly because it expects to be running from an uber JAR with all the dependencies available. Now we specifically add the path to the Gson library in those cases. The user won't notice but it makes life easier for developers. --- .../java/dev/jbang/spi/IntegrationManager.java | 14 +++++++++++++- src/main/java/dev/jbang/util/Util.java | 11 ++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/jbang/spi/IntegrationManager.java b/src/main/java/dev/jbang/spi/IntegrationManager.java index 75b8c993d..98918fc16 100644 --- a/src/main/java/dev/jbang/spi/IntegrationManager.java +++ b/src/main/java/dev/jbang/spi/IntegrationManager.java @@ -6,6 +6,7 @@ import java.io.BufferedReader; import java.io.BufferedWriter; +import java.io.File; import java.io.FileDescriptor; import java.io.FileOutputStream; import java.io.IOException; @@ -220,8 +221,19 @@ private static IntegrationResult runIntegrationExternal(IntegrationInput input, for (Map.Entry entry : properties.entrySet()) { args.add("-D" + entry.getKey() + "=" + entry.getValue()); } + + Path jbangJar = Util.getJarLocation(); args.add("-cp"); - args.add(Util.getJarLocation().toString()); + if (jbangJar.toString().endsWith(".jar")) { + args.add(jbangJar.toString()); + } else { + // We will assume that we're running inside an IDE or + // some kind of test environment and need to manually + // add the Gson dependency + Path gsonJar = Util.getJarLocation(Gson.class); + args.add(jbangJar + File.pathSeparator + gsonJar); + } + args.add("dev.jbang.spi.IntegrationManager"); if (Util.isVerbose()) { diff --git a/src/main/java/dev/jbang/util/Util.java b/src/main/java/dev/jbang/util/Util.java index 50d755692..21ec45f3f 100644 --- a/src/main/java/dev/jbang/util/Util.java +++ b/src/main/java/dev/jbang/util/Util.java @@ -1689,8 +1689,17 @@ public static boolean runningManagedJBang() { * @return An actual Path if it was found, or an empty path if it was not */ public static Path getJarLocation() { + return getJarLocation(VersionChecker.class); + } + + /** + * Determines the path to the JAR that contains the given class + * + * @return An actual Path if it was found, or an empty path if it was not + */ + public static Path getJarLocation(Class klazz) { try { - File jarFile = new File(VersionChecker.class.getProtectionDomain().getCodeSource().getLocation().toURI()); + File jarFile = new File(klazz.getProtectionDomain().getCodeSource().getLocation().toURI()); return jarFile.toPath(); } catch (URISyntaxException e) { // ignore From 2c44808fe65970542eb6834cf66bdf9956a78206 Mon Sep 17 00:00:00 2001 From: Tako Schotanus Date: Wed, 7 Jun 2023 17:42:13 +0200 Subject: [PATCH 4/5] feat: scripts can now implement integrations Before this change JBang would only look for integrations in the dependencies, now it also looks in the currently compiled code. --- src/main/java/dev/jbang/spi/IntegrationManager.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/dev/jbang/spi/IntegrationManager.java b/src/main/java/dev/jbang/spi/IntegrationManager.java index 98918fc16..f483700b8 100644 --- a/src/main/java/dev/jbang/spi/IntegrationManager.java +++ b/src/main/java/dev/jbang/spi/IntegrationManager.java @@ -26,6 +26,7 @@ import java.nio.file.Path; import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.annotation.Nonnull; @@ -79,7 +80,7 @@ public static IntegrationResult runIntegrations(Project prj, Path tmpJarDir, Pat ClassLoader old = Thread.currentThread().getContextClassLoader(); PrintStream oldout = System.out; try { - URLClassLoader integrationCl = getClassLoader(deps.values()); + URLClassLoader integrationCl = getClassLoader(tmpJarDir, deps.values()); Thread.currentThread().setContextClassLoader(integrationCl); String requestedJavaVersion = prj.getJavaVersion(); Set classNames = loadIntegrationClassNames(integrationCl); @@ -112,8 +113,9 @@ public static IntegrationResult runIntegrations(Project prj, Path tmpJarDir, Pat } @Nonnull - private static URLClassLoader getClassLoader(Collection deps) { - URL[] urls = deps.stream().map(path -> { + private static URLClassLoader getClassLoader(Path classes, Collection deps) { + Stream paths = Stream.concat(Stream.of(classes), deps.stream()); + URL[] urls = paths.map(path -> { try { return path.toUri().toURL(); } catch (MalformedURLException e) { @@ -282,7 +284,7 @@ public static void main(String... args) { String output = ""; boolean ok = false; try { - URLClassLoader integrationCl = getClassLoader(input.dependencies.values()); + URLClassLoader integrationCl = getClassLoader(input.classes, input.dependencies.values()); Thread.currentThread().setContextClassLoader(integrationCl); IntegrationResult result = runIntegrationEmbedded(input, integrationCl); output = parser.toJson(result); From 6661ad595eaa3c1908b2b2def030bdcf5e40a60a Mon Sep 17 00:00:00 2001 From: Tako Schotanus Date: Wed, 7 Jun 2023 18:10:41 +0200 Subject: [PATCH 5/5] test: added integration tests for integration --- itests/integration.feature | 29 +++++++++++++++++++++++++ itests/integration/IntegrationTest.java | 23 ++++++++++++++++++++ itests/integration/inttest.java | 9 ++++++++ itests/integration/jb-int.list | 1 + 4 files changed, 62 insertions(+) create mode 100644 itests/integration.feature create mode 100644 itests/integration/IntegrationTest.java create mode 100644 itests/integration/inttest.java create mode 100644 itests/integration/jb-int.list diff --git a/itests/integration.feature b/itests/integration.feature new file mode 100644 index 000000000..ae16ad4b2 --- /dev/null +++ b/itests/integration.feature @@ -0,0 +1,29 @@ +Feature: integration + + Scenario: integration success + * command('jbang integration/inttest.java') + * match err !contains 'Integration... (out)' + * match err contains 'Integration... (err)' + * match out contains "Integration test" + + Scenario: integration success, verbose + * command('jbang --verbose integration/inttest.java') + * match err contains 'Integration... (out)' + * match err contains 'Integration... (err)' + * match out contains "Integration test" + + Scenario: integration failure + * command('jbang -Dfailintegration=1 integration/inttest.java') + * match err !contains 'Integration... (out)' + * match err contains 'Integration... (err)' + * match err contains 'Issue running postBuild()' + * match err !contains 'Failing integration...' + * match exit == 1 + + Scenario: integration failure, verbose + * command('jbang -Dfailintegration=1 --verbose integration/inttest.java') + * match err contains 'Integration... (out)' + * match err contains 'Integration... (err)' + * match err contains 'Issue running postBuild()' + * match err contains 'Failing integration...' + * match exit == 1 diff --git a/itests/integration/IntegrationTest.java b/itests/integration/IntegrationTest.java new file mode 100644 index 000000000..fa1a53689 --- /dev/null +++ b/itests/integration/IntegrationTest.java @@ -0,0 +1,23 @@ +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +public class IntegrationTest { + public static Map postBuild(Path temporaryJar, + Path pomFile, + List> repositories, + List> dependencies, + List comments, + boolean nativeImage) { + System.out.println("Integration... (out)"); + System.err.println("Integration... (err)"); + if (System.getProperty("failintegration") != null) { + throw new RuntimeException("Failing integration..."); + } else { + System.out.println("Integration OK (out)"); + System.err.println("Integration OK (err)"); + return Collections.emptyMap(); + } + } +} diff --git a/itests/integration/inttest.java b/itests/integration/inttest.java new file mode 100644 index 000000000..74f1cb4df --- /dev/null +++ b/itests/integration/inttest.java @@ -0,0 +1,9 @@ + +//SOURCES IntegrationTest.java +//FILES META-INF/jbang-integration.list=jb-int.list + +class inttest { + public static void main(String... args) { + System.out.println("Integration test"); + } +} diff --git a/itests/integration/jb-int.list b/itests/integration/jb-int.list new file mode 100644 index 000000000..a0b2f88fe --- /dev/null +++ b/itests/integration/jb-int.list @@ -0,0 +1 @@ +IntegrationTest