From e722d150ec04b96306fccf26402bd6fbb501b424 Mon Sep 17 00:00:00 2001 From: Dai MIKURUBE Date: Mon, 3 Jun 2024 17:55:12 +0900 Subject: [PATCH] Install jruby-complete.jar, and set "jruby" When using JRuby, Embulk expects to have an Embulk System Property "jruby" with a "file:" URI, such as "jruby=file:///path/to/jruby-complete.9.x.y.z.jar" See EEP-6: JRuby as Optional https://github.com/embulk/embulk/blob/master/docs/eeps/eep-0006.md This change is to add a new "jruby" notation in "installEmbulkRunSet" to download jruby-complete.jar, and set the "jruby" property. --- .../gradle/runset/InstallEmbulkRunSet.java | 64 ++++++++++++++++++- .../gradle/runset/TestEmbulkRunSetPlugin.java | 21 +++++- src/test/resources/simple/build.gradle | 1 + 3 files changed, 82 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/embulk/gradle/runset/InstallEmbulkRunSet.java b/src/main/java/org/embulk/gradle/runset/InstallEmbulkRunSet.java index 948246d..7b167cd 100644 --- a/src/main/java/org/embulk/gradle/runset/InstallEmbulkRunSet.java +++ b/src/main/java/org/embulk/gradle/runset/InstallEmbulkRunSet.java @@ -31,6 +31,7 @@ import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.Set; import org.gradle.api.Action; import org.gradle.api.IllegalDependencyNotation; import org.gradle.api.InvalidUserDataException; @@ -64,8 +65,10 @@ public InstallEmbulkRunSet() { this.project = this.getProject(); this.logger = this.project.getLogger(); + this.embulkHome = null; this.embulkSystemProperties = new Properties(); this.embulkSystemPropertiesSource = null; + this.jrubyRelative = null; this.m2RepoRelative = DEFAULT_M2_REPO_RELATIVE; final ObjectFactory objectFactory = this.project.getObjects(); @@ -117,6 +120,45 @@ public void artifact(final Object dependencyNotation) { } } + /** + * Adds a JRuby-complete Maven artifact to be installed. + * + *

It tries to simulate Gradle's dependency notations, but it is yet far from perfect. + * + * @see org.gradle.api.internal.notations.DependencyNotationParser#create + */ + public InstallEmbulkRunSet jruby(final Object dependencyNotation) { + final Dependency dependency; + if (dependencyNotation instanceof CharSequence) { + dependency = this.dependencyFromCharSequence((CharSequence) dependencyNotation); + } else if (dependencyNotation instanceof Map) { + dependency = this.dependencyFromMap((Map) dependencyNotation); + } else { + throw new IllegalDependencyNotation("Supplied jruby module notation is invalid."); + } + + // Constructing an independent (detached) Configuration so that its dependencies are not affected by other plugins. + final Configuration configuration = this.project.getConfigurations().detachedConfiguration(dependency); + + final ResolvableDependencies resolvableDependencies = configuration.getIncoming(); + final ArtifactCollection artifactCollection = resolvableDependencies.getArtifacts(); + + // Getting the JAR file. + final ArrayList componentIds = new ArrayList<>(); + final Set resolvedArtifactResults = artifactCollection.getArtifacts(); + if (resolvedArtifactResults.isEmpty()) { + throw new IllegalDependencyNotation("Supplied jruby module notation is unavailable."); + } + if (resolvedArtifactResults.size() > 1) { + throw new IllegalDependencyNotation("Supplied jruby module notation has dependencies. Specify jruby-complete instead."); + } + + final ResolvedArtifactResult resolvedArtifactResult = resolvedArtifactResults.stream().findFirst().get(); + this.jrubyRelative = this.fromArtifact(resolvedArtifactResult, "jar"); + + return this; + } + public InstallEmbulkRunSet embulkHome(final File dir) { if (dir == null) { throw new InvalidUserDataException("Supplied embulkHome is null."); @@ -140,6 +182,8 @@ public InstallEmbulkRunSet embulkHome(final File dir) { this.logger.lifecycle("Supplied embulkHome \"{}\" does not exist, then will be created.", dir); } + this.embulkHome = dir.toPath(); + super.into(dir); return this; } @@ -185,18 +229,20 @@ public final Copy into(final Object destPath, final Action cop throw new InvalidUserDataException("\"into\" is not permitted in InstallEmbulkRunSet. Use \"embulkHome\" instead."); } - private void fromArtifact(final ResolvedArtifactResult resolvedArtifactResult, final String artifactType) { + private Path fromArtifact(final ResolvedArtifactResult resolvedArtifactResult, final String artifactType) { final ComponentIdentifier id = resolvedArtifactResult.getId().getComponentIdentifier(); final File file = resolvedArtifactResult.getFile(); if (id instanceof ModuleComponentIdentifier) { final Path modulePath = moduleToPath((ModuleComponentIdentifier) id); + final Path modulePathFromHome = this.m2RepoRelative.resolve(modulePath); this.logger.lifecycle("Setting to copy {}:{} into {}", id, artifactType, modulePath); this.logger.info("Cached file: {}", file); this.from(file, copy -> { - copy.into(this.m2RepoRelative.resolve(modulePath).toFile()); + copy.into(modulePathFromHome.toFile()); copy.setDuplicatesStrategy(DuplicatesStrategy.EXCLUDE); }); + return modulePathFromHome.resolve(file.getName()); } else if (id instanceof ProjectComponentIdentifier) { throw new IllegalDependencyNotation("Cannot install artifacts for a project component (" + id.getDisplayName() + ")"); } else { @@ -273,6 +319,16 @@ private static Map castMap(final Map map) { @Override @TaskAction protected void copy() { + if (this.embulkHome == null) { + throw new InvalidUserDataException("embulkHome is not supplied."); + } + + if (this.jrubyRelative != null) { + this.embulkSystemProperties.setProperty( + "jruby", + this.embulkHome.resolve(this.jrubyRelative).toUri().toString()); + } + if (this.embulkSystemPropertiesSource != null) { try (final OutputStream out = Files.newOutputStream(this.embulkSystemPropertiesSource)) { this.embulkSystemProperties.store( @@ -314,7 +370,11 @@ private synchronized void createPropertiesSourceAndSetToCopy() { private final Properties embulkSystemProperties; + private Path embulkHome; + private Path embulkSystemPropertiesSource; + private Path jrubyRelative; + private Path m2RepoRelative; } diff --git a/src/test/java/org/embulk/gradle/runset/TestEmbulkRunSetPlugin.java b/src/test/java/org/embulk/gradle/runset/TestEmbulkRunSetPlugin.java index 7fd8ad4..86272a0 100644 --- a/src/test/java/org/embulk/gradle/runset/TestEmbulkRunSetPlugin.java +++ b/src/test/java/org/embulk/gradle/runset/TestEmbulkRunSetPlugin.java @@ -19,9 +19,12 @@ import static org.embulk.gradle.runset.Util.prepareProjectDir; import static org.embulk.gradle.runset.Util.runGradle; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; @@ -34,7 +37,7 @@ public class TestEmbulkRunSetPlugin { @Test - public void testSimple(@TempDir Path tempDir) throws IOException { + public void testSimple(@TempDir Path tempDir) throws IOException, URISyntaxException { final Path projectDir = prepareProjectDir(tempDir, "simple"); runGradle(projectDir, "installEmbulkRunSet"); @@ -53,8 +56,22 @@ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attr try (final InputStream in = Files.newInputStream(propertiesPath)) { properties.load(in); } - assertEquals(2, properties.size()); + assertEquals(3, properties.size()); assertEquals("value", properties.getProperty("key")); assertEquals(Paths.get("lib").resolve("m2").resolve("repository").toString(), properties.getProperty("m2_repo")); + assertEquals("lib/m2/repository", properties.getProperty("m2_repo")); + final URI jrubyUri = new URI(properties.getProperty("jruby")); + assertEquals("file", jrubyUri.getScheme()); + final Path jrubyAbsolutePath = Paths.get(jrubyUri.getPath()); + assertTrue(jrubyAbsolutePath.isAbsolute()); + assertTrue(jrubyAbsolutePath.endsWith( + Paths.get("lib") + .resolve("m2") + .resolve("repository") + .resolve("org") + .resolve("jruby") + .resolve("jruby-complete") + .resolve("9.1.15.0") + .resolve("jruby-complete-9.1.15.0.jar"))); } } diff --git a/src/test/resources/simple/build.gradle b/src/test/resources/simple/build.gradle index c4be844..56cb489 100644 --- a/src/test/resources/simple/build.gradle +++ b/src/test/resources/simple/build.gradle @@ -8,6 +8,7 @@ repositories { installEmbulkRunSet { embulkHome file("${project.buildDir}/simple") + jruby "org.jruby:jruby-complete:9.1.15.0" m2RepoRelative "lib/m2/repository" embulkSystemProperty "key", "value" artifact "org.embulk:embulk-input-postgresql:0.13.2"