From 1fc579d7128928b323b693d583c83b811d3d4fb1 Mon Sep 17 00:00:00 2001 From: Davy Landman Date: Mon, 3 Oct 2022 16:45:43 +0200 Subject: [PATCH 01/17] Added fast path to avoid starting maven just to install dependencies --- .../rascalmpl/library/util/PathConfig.java | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/org/rascalmpl/library/util/PathConfig.java b/src/org/rascalmpl/library/util/PathConfig.java index 4b43dff1c8d..9be777b9b56 100644 --- a/src/org/rascalmpl/library/util/PathConfig.java +++ b/src/org/rascalmpl/library/util/PathConfig.java @@ -7,6 +7,7 @@ import java.io.StringReader; import java.io.StringWriter; import java.net.URISyntaxException; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -647,10 +648,28 @@ private static String computeMavenCommandName() { } } + private static final String dependencyPluginGroup = "org.apache.maven.plugins"; + private static final String dependencyPluginArtifact = "maven-dependency-plugin"; + private static final String dependencyPluginVersion = "2.8"; + private static void installNecessaryMavenPlugins(String mvnCommand) { try { - ProcessBuilder processBuilder = new ProcessBuilder(mvnCommand, "-q", "dependency:get", "-DgroupId=org.apache.maven.plugins", - "-DartifactId=maven-dependency-plugin", "-Dversion=2.8"); + var quickPath = + Paths.get(System.getProperty("user.home" ), + ".m2", "repository", + dependencyPluginGroup.replace(".", File.separator), + dependencyPluginArtifact, + dependencyPluginVersion, + dependencyPluginArtifact + "-" + dependencyPluginVersion + ".jar" + ); + + if (quickPath.toFile().exists()) { + // we find that the jar is already there, so no need to trigger maven just to ask it to install the file + return; + } + + ProcessBuilder processBuilder = new ProcessBuilder(mvnCommand, "-q", "dependency:get", "-DgroupId=" + dependencyPluginGroup, + "-DartifactId=" + dependencyPluginArtifact, "-Dversion=" + dependencyPluginVersion); Process process = processBuilder.start(); if (process.waitFor() != 0) { From 0e8b61a3baf9ad05512e6307a551ca4deea5bfb8 Mon Sep 17 00:00:00 2001 From: Davy Landman Date: Tue, 4 Oct 2022 16:11:45 +0200 Subject: [PATCH 02/17] Rewrote to using internal maven engine instead of forking jvm On windows increases speed from 14s to 2s --- pom.xml | 21 +++++ .../rascalmpl/library/util/PathConfig.java | 88 ++++++------------- 2 files changed, 47 insertions(+), 62 deletions(-) diff --git a/pom.xml b/pom.xml index 08d968e7a2d..2f846ef68d0 100644 --- a/pom.xml +++ b/pom.xml @@ -29,6 +29,7 @@ UTF-8 7.5.0 + 3.8.6 org.rascalmpl.shell.RascalShell 2 @@ -414,5 +415,25 @@ 1.72 provided + + org.apache.maven + maven-embedder + ${maven-version} + + + org.apache.maven.plugins + maven-dependency-plugin + 3.3.0 + + + org.slf4j + slf4j-simple + 1.7.36 + + + org.apache.maven + maven-compat + ${maven-version} + diff --git a/src/org/rascalmpl/library/util/PathConfig.java b/src/org/rascalmpl/library/util/PathConfig.java index 9be777b9b56..4b44b650246 100644 --- a/src/org/rascalmpl/library/util/PathConfig.java +++ b/src/org/rascalmpl/library/util/PathConfig.java @@ -1,12 +1,13 @@ package org.rascalmpl.library.util; -import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; -import java.io.InputStreamReader; +import java.io.PrintStream; import java.io.StringReader; import java.io.StringWriter; import java.net.URISyntaxException; +import java.nio.charset.StandardCharsets; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; @@ -14,8 +15,11 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.Set; +import java.util.regex.Pattern; +import org.apache.maven.cli.MavenCli; import org.rascalmpl.interpreter.Configuration; import org.rascalmpl.interpreter.utils.RascalManifest; import org.rascalmpl.uri.URIResolverRegistry; @@ -582,6 +586,10 @@ private static ISourceLocation setTargetScheme(ISourceLocation projectLoc) { } } + + private static final Pattern FIND_CLASS_PATH = Pattern.compile("org.apache.maven.plugin.dependency.fromDependencies.BuildClasspathMojo - Dependencies classpath:\\s+(.+)$", Pattern.MULTILINE); + + /** * See if there is a pom.xml and extract the compile-time classpath from a mvn run * if there is such a file. @@ -602,25 +610,22 @@ private static IList getPomXmlCompilerClasspath(ISourceLocation manifestRoot) { return vf.list(); } - String mvnCommand = computeMavenCommandName(); - - installNecessaryMavenPlugins(mvnCommand); - - // Note how we try to do this "offline" using the "-o" flag - ProcessBuilder processBuilder = new ProcessBuilder(mvnCommand, "-o", "dependency:build-classpath", - "-DincludeScope=compile"); - processBuilder.directory(new File(manifestRoot.getPath())); - - Process process = processBuilder.start(); - - try (BufferedReader processOutputReader = new BufferedReader(new InputStreamReader(process.getInputStream()))) { - - process.waitFor(); + var maven = new MavenCli(); + try (var output = new ByteArrayOutputStream()) { + Properties originalProperties = System.getProperties(); + // due to limitation in MavenCli, we have to set a global property. + System.setProperty(MavenCli.MULTIMODULE_PROJECT_DIRECTORY, manifestRoot.getPath()); + try (var out = new PrintStream(output, false, StandardCharsets.UTF_8)) { + maven.doMain(new String[] {"-o", "dependency:build-classpath", "-DincludeScope=compile"}, manifestRoot.getPath(), out, out); + } + finally { + System.setProperties(originalProperties ); + } + var mavenOutput = new String(output.toByteArray(), StandardCharsets.UTF_8); + var match = FIND_CLASS_PATH.matcher(mavenOutput); + var foundClassPath = match.find() ? match.group(1) : ""; - return processOutputReader.lines() - .filter(line -> !line.startsWith("[")) - .filter(line -> !line.contains("-----")) - .flatMap(line -> Arrays.stream(line.split(File.pathSeparator))) + return Arrays.stream(foundClassPath.split(File.pathSeparator) ) .filter(fileName -> new File(fileName).exists()) .map(elem -> { try { @@ -634,52 +639,11 @@ private static IList getPomXmlCompilerClasspath(ISourceLocation manifestRoot) { .collect(vf.listWriter()); } } - catch (IOException | InterruptedException e) { + catch (IOException | RuntimeException e) { return vf.list(); } } - private static String computeMavenCommandName() { - if (System.getProperty("os.name", "generic").startsWith("Windows")) { - return "mvn.cmd"; - } - else { - return "mvn"; - } - } - - private static final String dependencyPluginGroup = "org.apache.maven.plugins"; - private static final String dependencyPluginArtifact = "maven-dependency-plugin"; - private static final String dependencyPluginVersion = "2.8"; - - private static void installNecessaryMavenPlugins(String mvnCommand) { - try { - var quickPath = - Paths.get(System.getProperty("user.home" ), - ".m2", "repository", - dependencyPluginGroup.replace(".", File.separator), - dependencyPluginArtifact, - dependencyPluginVersion, - dependencyPluginArtifact + "-" + dependencyPluginVersion + ".jar" - ); - - if (quickPath.toFile().exists()) { - // we find that the jar is already there, so no need to trigger maven just to ask it to install the file - return; - } - - ProcessBuilder processBuilder = new ProcessBuilder(mvnCommand, "-q", "dependency:get", "-DgroupId=" + dependencyPluginGroup, - "-DartifactId=" + dependencyPluginArtifact, "-Dversion=" + dependencyPluginVersion); - - Process process = processBuilder.start(); - if (process.waitFor() != 0) { - throw new IOException("mvn dependency:get returned non-zero"); - } - } - catch (IOException | InterruptedException e) { - System.err.println("[WARNING] Could not install exec-maven-plugin; classpath resolution may be incomplete hereafter: " + e.getMessage()); - } - } public ISourceLocation getBin() { return bin; From f5748534a9d3800a54b4f707dd0b2f58a1e4e525 Mon Sep 17 00:00:00 2001 From: Davy Landman Date: Tue, 4 Oct 2022 16:38:02 +0200 Subject: [PATCH 03/17] Rewrote to calling maven without changing global properties (but sadly, changing output streams, hoping it's not a race) --- .../rascalmpl/library/util/PathConfig.java | 38 ++++++++++++++----- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/org/rascalmpl/library/util/PathConfig.java b/src/org/rascalmpl/library/util/PathConfig.java index 4b44b650246..9c72c8a01d5 100644 --- a/src/org/rascalmpl/library/util/PathConfig.java +++ b/src/org/rascalmpl/library/util/PathConfig.java @@ -8,18 +8,19 @@ import java.io.StringWriter; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Properties; +import java.util.Objects; import java.util.Set; import java.util.regex.Pattern; +import org.apache.maven.cli.CliRequest; import org.apache.maven.cli.MavenCli; +import org.codehaus.plexus.classworlds.ClassWorld; import org.rascalmpl.interpreter.Configuration; import org.rascalmpl.interpreter.utils.RascalManifest; import org.rascalmpl.uri.URIResolverRegistry; @@ -612,14 +613,16 @@ private static IList getPomXmlCompilerClasspath(ISourceLocation manifestRoot) { var maven = new MavenCli(); try (var output = new ByteArrayOutputStream()) { - Properties originalProperties = System.getProperties(); - // due to limitation in MavenCli, we have to set a global property. - System.setProperty(MavenCli.MULTIMODULE_PROJECT_DIRECTORY, manifestRoot.getPath()); + var oldOut = System.out; + var oldErr = System.err; try (var out = new PrintStream(output, false, StandardCharsets.UTF_8)) { - maven.doMain(new String[] {"-o", "dependency:build-classpath", "-DincludeScope=compile"}, manifestRoot.getPath(), out, out); + System.setOut(out); + System.setErr(out); + maven.doMain(buildRequest(new String[] {"-o", "dependency:build-classpath", "-DincludeScope=compile"}, manifestRoot)); } finally { - System.setProperties(originalProperties ); + System.setOut(oldOut); + System.setErr(oldErr); } var mavenOutput = new String(output.toByteArray(), StandardCharsets.UTF_8); var match = FIND_CLASS_PATH.matcher(mavenOutput); @@ -635,15 +638,32 @@ private static IList getPomXmlCompilerClasspath(ISourceLocation manifestRoot) { return null; } }) - .filter(e -> e != null) + .filter(Objects::nonNull) .collect(vf.listWriter()); } } - catch (IOException | RuntimeException e) { + catch (IOException | RuntimeException | ReflectiveOperationException e) { return vf.list(); } } + private static void setField(CliRequest req, String fieldName, Object value) throws ReflectiveOperationException { + var field = CliRequest.class.getDeclaredField(fieldName); + field.setAccessible(true); + field.set(req, value); + } + + private static CliRequest buildRequest(String[] args, ISourceLocation manifestRoot) throws ReflectiveOperationException { + // we need to set a field that the default class doesn't set + // it's a work around around a bug in the MavenCli code + var cons = CliRequest.class.getDeclaredConstructor(String[].class, ClassWorld.class); + cons.setAccessible(true); + var result = cons.newInstance(args, null); + setField(result, "workingDirectory", manifestRoot.getPath()); + setField(result, "multiModuleProjectDirectory", new File(manifestRoot.getPath())); + return result; + } + public ISourceLocation getBin() { return bin; From 6dc6715dcd42c8ce3a25bbc993d01df1d09768e0 Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Mon, 22 Jul 2024 14:40:35 +0200 Subject: [PATCH 04/17] Fixed path normalization for embedded maven Co-authored-by: Davy Landman --- src/org/rascalmpl/library/util/PathConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/rascalmpl/library/util/PathConfig.java b/src/org/rascalmpl/library/util/PathConfig.java index a295ac2a95c..0f5c82eb876 100644 --- a/src/org/rascalmpl/library/util/PathConfig.java +++ b/src/org/rascalmpl/library/util/PathConfig.java @@ -708,7 +708,7 @@ private static CliRequest buildRequest(String[] args, ISourceLocation manifestRo var cons = CliRequest.class.getDeclaredConstructor(String[].class, ClassWorld.class); cons.setAccessible(true); var result = cons.newInstance(args, null); - setField(result, "workingDirectory", manifestRoot.getPath()); + setField(result, "workingDirectory", new File(manifestRoot.getPath()).getPath()); setField(result, "multiModuleProjectDirectory", new File(manifestRoot.getPath())); return result; } From a2ce678b29ffa3d77c1d91d24e51c02172cc710c Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Mon, 22 Jul 2024 14:42:54 +0200 Subject: [PATCH 05/17] Updated maven library version --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 540e5a07a19..44dfedb511f 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ UTF-8 7.5.0 - 3.8.6 + 3.9.8 org.rascalmpl.shell.RascalShell 2 11 @@ -492,7 +492,7 @@ org.apache.maven.plugins maven-dependency-plugin - 3.3.0 + 3.7.1 org.slf4j From df9a698289cf3826bb3070d5492034c4eff19795 Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Tue, 30 Jul 2024 16:42:14 +0200 Subject: [PATCH 06/17] Added another necessary dependency for maven-embedder --- pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pom.xml b/pom.xml index 44dfedb511f..a4e4e9e3787 100644 --- a/pom.xml +++ b/pom.xml @@ -504,5 +504,10 @@ maven-compat ${maven-version} + + org.apache.maven + maven-core + ${maven-version} + From d5cff33858c7403a23f612722649bb94524d2eb2 Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Tue, 20 Aug 2024 14:31:50 +0200 Subject: [PATCH 07/17] Configured maven-shade-plugin to correctly shade required files for dependency injection in maven-embedder --- pom.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pom.xml b/pom.xml index a4e4e9e3787..4617509e913 100644 --- a/pom.xml +++ b/pom.xml @@ -292,7 +292,9 @@ org/rascalmpl/uri/resolvers.config io/usethesource/vallang/type/types.config + META-INF/sisu/javax.inject.Named + From 0bcaddae356447e6763a86b87b3ff1872a7e23cc Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Tue, 20 Aug 2024 14:32:16 +0200 Subject: [PATCH 08/17] Fixed regular expression to obtain the classpath from Maven's output --- src/org/rascalmpl/library/util/PathConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/rascalmpl/library/util/PathConfig.java b/src/org/rascalmpl/library/util/PathConfig.java index 0f5c82eb876..5ba3a6b08e0 100644 --- a/src/org/rascalmpl/library/util/PathConfig.java +++ b/src/org/rascalmpl/library/util/PathConfig.java @@ -637,7 +637,7 @@ private static ISourceLocation setTargetScheme(ISourceLocation projectLoc) { } - private static final Pattern FIND_CLASS_PATH = Pattern.compile("org.apache.maven.plugin.dependency.fromDependencies.BuildClasspathMojo - Dependencies classpath:\\s+(.+)$", Pattern.MULTILINE); + private static final Pattern FIND_CLASS_PATH = Pattern.compile("org.apache.maven.plugins.dependency.fromDependencies.BuildClasspathMojo - Dependencies classpath:\\s+(.+)$", Pattern.MULTILINE); /** From cb9851d1548a931b6d4e76d7cfbe04389e2213d8 Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Tue, 20 Aug 2024 15:03:26 +0200 Subject: [PATCH 09/17] Layout --- src/org/rascalmpl/library/util/PathConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/org/rascalmpl/library/util/PathConfig.java b/src/org/rascalmpl/library/util/PathConfig.java index 5ba3a6b08e0..0060bf51c35 100644 --- a/src/org/rascalmpl/library/util/PathConfig.java +++ b/src/org/rascalmpl/library/util/PathConfig.java @@ -677,7 +677,7 @@ private static IList getPomXmlCompilerClasspath(ISourceLocation manifestRoot) { var match = FIND_CLASS_PATH.matcher(mavenOutput); var foundClassPath = match.find() ? match.group(1) : ""; - return Arrays.stream(foundClassPath.split(File.pathSeparator) ) + return Arrays.stream(foundClassPath.split(File.pathSeparator)) .filter(fileName -> new File(fileName).exists()) .map(elem -> { try { @@ -696,7 +696,7 @@ private static IList getPomXmlCompilerClasspath(ISourceLocation manifestRoot) { } } - private static void setField(CliRequest req, String fieldName, Object value) throws ReflectiveOperationException { + private static void setField(CliRequest req, String fieldName, Object value) throws ReflectiveOperationException { var field = CliRequest.class.getDeclaredField(fieldName); field.setAccessible(true); field.set(req, value); From d5c655bf2304925ea0bbaf5b6b505d377cbbfe98 Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Tue, 20 Aug 2024 17:38:14 +0200 Subject: [PATCH 10/17] No longer manipulating System.out and System.err streams, instead writing maven classpath to disk --- .../rascalmpl/library/util/PathConfig.java | 53 ++++++++----------- 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/src/org/rascalmpl/library/util/PathConfig.java b/src/org/rascalmpl/library/util/PathConfig.java index 0060bf51c35..709c44e2885 100644 --- a/src/org/rascalmpl/library/util/PathConfig.java +++ b/src/org/rascalmpl/library/util/PathConfig.java @@ -1,14 +1,12 @@ package org.rascalmpl.library.util; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; -import java.io.PrintStream; import java.io.StringReader; import java.io.StringWriter; import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -661,35 +659,26 @@ private static IList getPomXmlCompilerClasspath(ISourceLocation manifestRoot) { } var maven = new MavenCli(); - try (var output = new ByteArrayOutputStream()) { - var oldOut = System.out; - var oldErr = System.err; - try (var out = new PrintStream(output, false, StandardCharsets.UTF_8)) { - System.setOut(out); - System.setErr(out); - maven.doMain(buildRequest(new String[] {"-o", "dependency:build-classpath", "-DincludeScope=compile"}, manifestRoot)); - } - finally { - System.setOut(oldOut); - System.setErr(oldErr); - } - var mavenOutput = new String(output.toByteArray(), StandardCharsets.UTF_8); - var match = FIND_CLASS_PATH.matcher(mavenOutput); - var foundClassPath = match.find() ? match.group(1) : ""; - - return Arrays.stream(foundClassPath.split(File.pathSeparator)) - .filter(fileName -> new File(fileName).exists()) - .map(elem -> { - try { - return URIUtil.createFileLocation(elem); - } - catch (URISyntaxException e) { - return null; - } - }) - .filter(Objects::nonNull) - .collect(vf.listWriter()); - } + var tempFile = Files.createTempFile("rascal-classpath-", ".tmp"); + + maven.doMain(buildRequest(new String[] {"-o", "dependency:build-classpath", "-DincludeScope=compile", "-Dmdep.outputFile=" + tempFile.toString()}, manifestRoot)); + + var mavenOutput = Files.readAllLines(tempFile); + var match = FIND_CLASS_PATH.matcher(mavenOutput.get(0)); + var foundClassPath = match.find() ? match.group(1) : ""; + + return Arrays.stream(foundClassPath.split(File.pathSeparator)) + .filter(fileName -> new File(fileName).exists()) + .map(elem -> { + try { + return URIUtil.createFileLocation(elem); + } + catch (URISyntaxException e) { + return null; + } + }) + .filter(Objects::nonNull) + .collect(vf.listWriter()); } catch (IOException | RuntimeException | ReflectiveOperationException e) { return vf.list(); From 2aab716589f0832f0a3f690678613dabeac4b2f2 Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Tue, 27 Aug 2024 09:43:41 +0200 Subject: [PATCH 11/17] Correctly extracting class path from maven output --- src/org/rascalmpl/library/util/PathConfig.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/org/rascalmpl/library/util/PathConfig.java b/src/org/rascalmpl/library/util/PathConfig.java index 709c44e2885..3de8cdce5a9 100644 --- a/src/org/rascalmpl/library/util/PathConfig.java +++ b/src/org/rascalmpl/library/util/PathConfig.java @@ -634,10 +634,6 @@ private static ISourceLocation setTargetScheme(ISourceLocation projectLoc) { } } - - private static final Pattern FIND_CLASS_PATH = Pattern.compile("org.apache.maven.plugins.dependency.fromDependencies.BuildClasspathMojo - Dependencies classpath:\\s+(.+)$", Pattern.MULTILINE); - - /** * See if there is a pom.xml and extract the compile-time classpath from a mvn run * if there is such a file. @@ -661,11 +657,9 @@ private static IList getPomXmlCompilerClasspath(ISourceLocation manifestRoot) { var maven = new MavenCli(); var tempFile = Files.createTempFile("rascal-classpath-", ".tmp"); - maven.doMain(buildRequest(new String[] {"-o", "dependency:build-classpath", "-DincludeScope=compile", "-Dmdep.outputFile=" + tempFile.toString()}, manifestRoot)); + maven.doMain(buildRequest(new String[] {"-quiet", "-o", "dependency:build-classpath", "-DincludeScope=compile", "-Dmdep.outputFile=" + tempFile.toString()}, manifestRoot)); - var mavenOutput = Files.readAllLines(tempFile); - var match = FIND_CLASS_PATH.matcher(mavenOutput.get(0)); - var foundClassPath = match.find() ? match.group(1) : ""; + var foundClassPath = Files.readAllLines(tempFile).get(0); return Arrays.stream(foundClassPath.split(File.pathSeparator)) .filter(fileName -> new File(fileName).exists()) From 90271d3b71066d10adbe5267eeb74367203bc46c Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Tue, 10 Sep 2024 15:20:07 +0200 Subject: [PATCH 12/17] Changed slf4j dependency to suppress maven output to the REPL --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 668c405d868..8a86a969302 100644 --- a/pom.xml +++ b/pom.xml @@ -528,7 +528,7 @@ org.slf4j - slf4j-simple + slf4j-nop 1.7.36 From 0529f26f1ba50ce47ba286fe2a2bf434ac95d6d1 Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Tue, 10 Sep 2024 15:20:28 +0200 Subject: [PATCH 13/17] Removed now-redundant constant --- src/org/rascalmpl/library/util/PathConfig.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/org/rascalmpl/library/util/PathConfig.java b/src/org/rascalmpl/library/util/PathConfig.java index 3de8cdce5a9..ea99e935a99 100644 --- a/src/org/rascalmpl/library/util/PathConfig.java +++ b/src/org/rascalmpl/library/util/PathConfig.java @@ -15,7 +15,6 @@ import java.util.Map; import java.util.Objects; import java.util.Set; -import java.util.regex.Pattern; import org.apache.maven.cli.CliRequest; import org.apache.maven.cli.MavenCli; @@ -66,8 +65,6 @@ public class PathConfig { private static List defaultClassloaders; private static ISourceLocation defaultBin; - private static final String WINDOWS_ROOT_TRUSTSTORE_TYPE_DEFINITION = "-Djavax.net.ssl.trustStoreType=WINDOWS-ROOT"; - public static enum RascalConfigMode { INTERPETER, COMPILER From d30a696b09e4e38e5ab4dc2a699588ff8dc8a9f6 Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Wed, 11 Sep 2024 23:05:14 +0200 Subject: [PATCH 14/17] Created separate class for Maven interaction --- src/org/rascalmpl/library/util/Maven.java | 84 +++++++++++++++++++ .../rascalmpl/library/util/PathConfig.java | 46 ++-------- 2 files changed, 89 insertions(+), 41 deletions(-) create mode 100644 src/org/rascalmpl/library/util/Maven.java diff --git a/src/org/rascalmpl/library/util/Maven.java b/src/org/rascalmpl/library/util/Maven.java new file mode 100644 index 00000000000..f71ceb28758 --- /dev/null +++ b/src/org/rascalmpl/library/util/Maven.java @@ -0,0 +1,84 @@ +package org.rascalmpl.library.util; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; + +import org.apache.maven.cli.CliRequest; +import org.apache.maven.cli.MavenCli; +import org.codehaus.plexus.classworlds.ClassWorld; +import org.rascalmpl.uri.URIResolverRegistry; +import org.rascalmpl.uri.URIUtil; + +import io.usethesource.vallang.ISourceLocation; + +public class Maven { + /** + * Calls maven with the provided arguments. The working directory will be set to `manifestRoot`, + * which should contain a `pom.xml` file. If `outputFile` refers to an existing file, its contents + * will the read and returned after Maven concludes. + * + * Maven's output is fully suppressed. However, it is often possible to redirect (parts of) the output + * to a file. For instance, the output of `mvn dependency:build-classpath` can be redicted to a file + * by providing an additional argument `-Dmdep.outputFile=/path/to/file`. + */ + public static List runCommand(List args, ISourceLocation manifestRoot, Path outputFile) { + try { + ISourceLocation pomxml = URIUtil.getChildLocation(manifestRoot, "pom.xml"); + pomxml = URIResolverRegistry.getInstance().logicalToPhysical(pomxml); + manifestRoot = URIResolverRegistry.getInstance().logicalToPhysical(manifestRoot); + + if (!"file".equals(manifestRoot.getScheme())) { + throw new IllegalArgumentException("`manifestRoot` could not be resolved"); + } + + if (!URIResolverRegistry.getInstance().exists(pomxml)) { + throw new IllegalArgumentException("`manifestRoot` does not contain pom.xml"); + } + + var maven = new MavenCli(); + maven.doMain(buildRequest(args.toArray(String[]::new), manifestRoot)); + + if (outputFile != null && Files.exists(outputFile)) { + return Files.readAllLines(outputFile); + } + } catch (IOException | ReflectiveOperationException e) { + // Fall through to return the empty list + } + + return Collections.emptyList(); + } + + /** + * Calls maven with the provided arguments. The working directory will be set to `manifestRoot`, + * which should contain a `pom.xml` file. Maven's output is fully suppressed. + */ + public static void runCommand(List args, ISourceLocation manifestRoot) { + runCommand(args, manifestRoot, null); + } + + private static void setField(CliRequest req, String fieldName, Object value) throws ReflectiveOperationException { + var field = CliRequest.class.getDeclaredField(fieldName); + field.setAccessible(true); + field.set(req, value); + } + + private static CliRequest buildRequest(String[] args, ISourceLocation manifestRoot) throws ReflectiveOperationException { + // we need to set a field that the default class doesn't set + // it's a work around around a bug in the MavenCli code + var cons = CliRequest.class.getDeclaredConstructor(String[].class, ClassWorld.class); + cons.setAccessible(true); + var result = cons.newInstance(args, null); + var manifestRootFile = new File(manifestRoot.getPath()); + setField(result, "workingDirectory", manifestRootFile.getPath()); + setField(result, "multiModuleProjectDirectory", manifestRootFile); + return result; + } + + public static Path getTempFile(String kind) throws IOException { + return Files.createTempFile("rascal-maven-" + kind + "-", ".tmp"); + } +} diff --git a/src/org/rascalmpl/library/util/PathConfig.java b/src/org/rascalmpl/library/util/PathConfig.java index ea99e935a99..ccb479d8240 100644 --- a/src/org/rascalmpl/library/util/PathConfig.java +++ b/src/org/rascalmpl/library/util/PathConfig.java @@ -6,7 +6,6 @@ import java.io.StringReader; import java.io.StringWriter; import java.net.URISyntaxException; -import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -16,9 +15,6 @@ import java.util.Objects; import java.util.Set; -import org.apache.maven.cli.CliRequest; -import org.apache.maven.cli.MavenCli; -import org.codehaus.plexus.classworlds.ClassWorld; import org.rascalmpl.interpreter.Configuration; import org.rascalmpl.interpreter.utils.RascalManifest; import org.rascalmpl.uri.ILogicalSourceLocationResolver; @@ -639,26 +635,11 @@ private static ISourceLocation setTargetScheme(ISourceLocation projectLoc) { */ private static IList getPomXmlCompilerClasspath(ISourceLocation manifestRoot) { try { - ISourceLocation pomxml = URIUtil.getChildLocation(manifestRoot, "pom.xml"); - pomxml = URIResolverRegistry.getInstance().logicalToPhysical(pomxml); - manifestRoot = URIResolverRegistry.getInstance().logicalToPhysical(manifestRoot); + var tempFile = Maven.getTempFile("classpath"); + var mavenOutput = Maven.runCommand(List.of("-quiet", "-o", "dependency:build-classpath", "-DincludeScope=compile", "-Dmdep.outputFile=" + tempFile.toString()), manifestRoot, tempFile); - if (!"file".equals(manifestRoot.getScheme())) { - return vf.list(); - } - - if (!URIResolverRegistry.getInstance().exists(pomxml)) { - return vf.list(); - } - - var maven = new MavenCli(); - var tempFile = Files.createTempFile("rascal-classpath-", ".tmp"); - - maven.doMain(buildRequest(new String[] {"-quiet", "-o", "dependency:build-classpath", "-DincludeScope=compile", "-Dmdep.outputFile=" + tempFile.toString()}, manifestRoot)); - - var foundClassPath = Files.readAllLines(tempFile).get(0); - - return Arrays.stream(foundClassPath.split(File.pathSeparator)) + // The classpath will be written to the temp file on a single line + return Arrays.stream(mavenOutput.get(0).split(File.pathSeparator)) .filter(fileName -> new File(fileName).exists()) .map(elem -> { try { @@ -671,28 +652,11 @@ private static IList getPomXmlCompilerClasspath(ISourceLocation manifestRoot) { .filter(Objects::nonNull) .collect(vf.listWriter()); } - catch (IOException | RuntimeException | ReflectiveOperationException e) { + catch (IOException | RuntimeException e) { return vf.list(); } } - private static void setField(CliRequest req, String fieldName, Object value) throws ReflectiveOperationException { - var field = CliRequest.class.getDeclaredField(fieldName); - field.setAccessible(true); - field.set(req, value); - } - - private static CliRequest buildRequest(String[] args, ISourceLocation manifestRoot) throws ReflectiveOperationException { - // we need to set a field that the default class doesn't set - // it's a work around around a bug in the MavenCli code - var cons = CliRequest.class.getDeclaredConstructor(String[].class, ClassWorld.class); - cons.setAccessible(true); - var result = cons.newInstance(args, null); - setField(result, "workingDirectory", new File(manifestRoot.getPath()).getPath()); - setField(result, "multiModuleProjectDirectory", new File(manifestRoot.getPath())); - return result; - } - public ISourceLocation getBin() { return bin; } From d181d8832074d2eb67253a494755fb70b7eca2a6 Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Tue, 17 Sep 2024 10:59:20 +0200 Subject: [PATCH 15/17] Fully qualified dependency plugin; removed quiet argument from maven call as all output is suppressed anyway --- src/org/rascalmpl/library/util/PathConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/org/rascalmpl/library/util/PathConfig.java b/src/org/rascalmpl/library/util/PathConfig.java index ccb479d8240..a76fb5661a7 100644 --- a/src/org/rascalmpl/library/util/PathConfig.java +++ b/src/org/rascalmpl/library/util/PathConfig.java @@ -636,7 +636,7 @@ private static ISourceLocation setTargetScheme(ISourceLocation projectLoc) { private static IList getPomXmlCompilerClasspath(ISourceLocation manifestRoot) { try { var tempFile = Maven.getTempFile("classpath"); - var mavenOutput = Maven.runCommand(List.of("-quiet", "-o", "dependency:build-classpath", "-DincludeScope=compile", "-Dmdep.outputFile=" + tempFile.toString()), manifestRoot, tempFile); + var mavenOutput = Maven.runCommand(List.of("-o", "org.apache.maven.plugins:maven-dependency-plugin:3.8.0:build-classpath", "-DincludeScope=compile", "-Dmdep.outputFile=" + tempFile.toString()), manifestRoot, tempFile); // The classpath will be written to the temp file on a single line return Arrays.stream(mavenOutput.get(0).split(File.pathSeparator)) From badd6e0b6f37c04cc49685cd4f72c76fb2200449 Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Tue, 17 Sep 2024 17:10:47 +0200 Subject: [PATCH 16/17] Make sure that maven-dependency-plugin is downloaded when not yet present --- src/org/rascalmpl/library/util/PathConfig.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/org/rascalmpl/library/util/PathConfig.java b/src/org/rascalmpl/library/util/PathConfig.java index a76fb5661a7..135e929bafd 100644 --- a/src/org/rascalmpl/library/util/PathConfig.java +++ b/src/org/rascalmpl/library/util/PathConfig.java @@ -635,8 +635,13 @@ private static ISourceLocation setTargetScheme(ISourceLocation projectLoc) { */ private static IList getPomXmlCompilerClasspath(ISourceLocation manifestRoot) { try { + String mavenDependencyPlugin = "org.apache.maven.plugins:maven-dependency-plugin:3.8.0"; + // First, make sure that maven-dependency-plugin is downloaded when not available + Maven.runCommand(List.of(mavenDependencyPlugin + ":do-nothing"), manifestRoot); + + // Now, actually let maven build the classpath. Note that this is in offline mode as to not download any dependencies var tempFile = Maven.getTempFile("classpath"); - var mavenOutput = Maven.runCommand(List.of("-o", "org.apache.maven.plugins:maven-dependency-plugin:3.8.0:build-classpath", "-DincludeScope=compile", "-Dmdep.outputFile=" + tempFile.toString()), manifestRoot, tempFile); + var mavenOutput = Maven.runCommand(List.of("-o", mavenDependencyPlugin + ":build-classpath", "-DincludeScope=compile", "-Dmdep.outputFile=" + tempFile.toString()), manifestRoot, tempFile); // The classpath will be written to the temp file on a single line return Arrays.stream(mavenOutput.get(0).split(File.pathSeparator)) From c82fbc9a13aaa37e0ef1b219470b0f93e3a32d14 Mon Sep 17 00:00:00 2001 From: Rodin Aarssen Date: Mon, 25 Nov 2024 17:14:39 +0100 Subject: [PATCH 17/17] Added missing license header --- src/org/rascalmpl/library/util/Maven.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/org/rascalmpl/library/util/Maven.java b/src/org/rascalmpl/library/util/Maven.java index f71ceb28758..59b678a3d5e 100644 --- a/src/org/rascalmpl/library/util/Maven.java +++ b/src/org/rascalmpl/library/util/Maven.java @@ -1,3 +1,15 @@ +/** + * Copyright (c) 2024, Rodin Aarssen, Swat.engineering + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ package org.rascalmpl.library.util; import java.io.File;