summaryrefslogtreecommitdiffstats
path: root/bundle-plugin/src/main/java/com/yahoo/container/plugin
diff options
context:
space:
mode:
Diffstat (limited to 'bundle-plugin/src/main/java/com/yahoo/container/plugin')
-rw-r--r--bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/Artifacts.java29
-rw-r--r--bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/AssembleTestBundleMojo.java5
-rw-r--r--bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateTestBundleOsgiManifestMojo.java5
-rw-r--r--bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/TestBundleDependencyScopeTranslator.java122
-rw-r--r--bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/TestProvidedArtifacts.java73
5 files changed, 145 insertions, 89 deletions
diff --git a/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/Artifacts.java b/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/Artifacts.java
index bc6a970140d..0dbed043de0 100644
--- a/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/Artifacts.java
+++ b/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/Artifacts.java
@@ -13,7 +13,16 @@ import java.util.List;
* @author ollivir
*/
class Artifacts {
+ interface ScopeTranslator {
+ String scopeOf(Artifact artifact);
+ }
+
+ static class NoopScopeTranslator implements ScopeTranslator {
+ @Override public String scopeOf(Artifact artifact) { return artifact.getScope(); }
+ }
+
static class ArtifactSet {
+
private final List<Artifact> jarArtifactsToInclude;
private final List<Artifact> jarArtifactsProvided;
private final List<Artifact> nonJarArtifacts;
@@ -40,29 +49,25 @@ class Artifacts {
}
}
- static ArtifactSet getArtifacts(MavenProject project) { return getArtifacts(project, false, null); }
+ static ArtifactSet getArtifacts(MavenProject project) { return getArtifacts(project, new NoopScopeTranslator()); }
- static ArtifactSet getArtifacts(MavenProject project, boolean includeTestArtifacts, String testProvidedConfig) {
- TestProvidedArtifacts testProvidedArtifacts = TestProvidedArtifacts.from(project.getArtifactMap(), testProvidedConfig);
+ static ArtifactSet getArtifacts(MavenProject project, ScopeTranslator scopeTranslator) {
List<Artifact> jarArtifactsToInclude = new ArrayList<>();
List<Artifact> jarArtifactsProvided = new ArrayList<>();
List<Artifact> nonJarArtifactsToInclude = new ArrayList<>();
List<Artifact> nonJarArtifactsProvided = new ArrayList<>();
for (Artifact artifact : project.getArtifacts()) {
+ String scope = scopeTranslator.scopeOf(artifact);
if ("jar".equals(artifact.getType())) {
- if (includeTestArtifacts && testProvidedArtifacts.isTestProvided(artifact)) {
- jarArtifactsProvided.add(artifact);
- } else if (Artifact.SCOPE_COMPILE.equals(artifact.getScope())) {
+ if (Artifact.SCOPE_COMPILE.equals(scope)) {
jarArtifactsToInclude.add(artifact);
- } else if (Artifact.SCOPE_PROVIDED.equals(artifact.getScope())) {
+ } else if (Artifact.SCOPE_PROVIDED.equals(scope)) {
jarArtifactsProvided.add(artifact);
- } else if (includeTestArtifacts && Artifact.SCOPE_TEST.equals(artifact.getScope())) {
- jarArtifactsToInclude.add(artifact);
}
} else {
- if (Artifact.SCOPE_COMPILE.equals(artifact.getScope())) {
+ if (Artifact.SCOPE_COMPILE.equals(scope)) {
nonJarArtifactsToInclude.add(artifact);
- } else if (Artifact.SCOPE_PROVIDED.equals(artifact.getScope())) {
+ } else if (Artifact.SCOPE_PROVIDED.equals(scope)) {
nonJarArtifactsProvided.add(artifact);
}
}
@@ -72,6 +77,6 @@ class Artifacts {
}
static Collection<Artifact> getArtifactsToInclude(MavenProject project) {
- return getArtifacts(project, false, null).getJarArtifactsToInclude();
+ return getArtifacts(project, new NoopScopeTranslator()).getJarArtifactsToInclude();
}
}
diff --git a/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/AssembleTestBundleMojo.java b/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/AssembleTestBundleMojo.java
index ab827275f53..ddf382b02dc 100644
--- a/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/AssembleTestBundleMojo.java
+++ b/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/AssembleTestBundleMojo.java
@@ -20,11 +20,12 @@ import static com.yahoo.container.plugin.mojo.TestBundleUtils.manifestFile;
public class AssembleTestBundleMojo extends AbstractAssembleBundleMojo {
@Parameter
- private String testProvidedArtifacts;
+ private String testBundleScopeOverrides;
@Override
public void execute() throws MojoExecutionException {
- Artifacts.ArtifactSet artifacts = Artifacts.getArtifacts(project, true, testProvidedArtifacts);
+ Artifacts.ArtifactSet artifacts = Artifacts.getArtifacts(
+ project, TestBundleDependencyScopeTranslator.from(project.getArtifactMap(), testBundleScopeOverrides));
JarArchiver archiver = new JarArchiver();
addDirectory(archiver, Paths.get(project.getBuild().getOutputDirectory()));
addDirectory(archiver, Paths.get(project.getBuild().getTestOutputDirectory()));
diff --git a/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateTestBundleOsgiManifestMojo.java b/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateTestBundleOsgiManifestMojo.java
index 811aff87b7e..0d4b4dbc8a4 100644
--- a/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateTestBundleOsgiManifestMojo.java
+++ b/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/GenerateTestBundleOsgiManifestMojo.java
@@ -31,11 +31,12 @@ import static java.util.stream.Collectors.toList;
public class GenerateTestBundleOsgiManifestMojo extends AbstractGenerateOsgiManifestMojo {
@Parameter
- private String testProvidedArtifacts;
+ private String testBundleScopeOverrides;
public void execute() throws MojoExecutionException {
try {
- Artifacts.ArtifactSet artifactSet = Artifacts.getArtifacts(project, true, testProvidedArtifacts);
+ Artifacts.ArtifactSet artifactSet = Artifacts.getArtifacts(
+ project, TestBundleDependencyScopeTranslator.from(project.getArtifactMap(), testBundleScopeOverrides));
List<File> providedJars = artifactSet.getJarArtifactsProvided().stream()
.map(Artifact::getFile)
diff --git a/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/TestBundleDependencyScopeTranslator.java b/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/TestBundleDependencyScopeTranslator.java
new file mode 100644
index 00000000000..9ad0a0e34ba
--- /dev/null
+++ b/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/TestBundleDependencyScopeTranslator.java
@@ -0,0 +1,122 @@
+// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.container.plugin.mojo;
+
+import org.apache.maven.artifact.Artifact;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.logging.Logger;
+
+import static java.util.stream.Collectors.toList;
+
+/**
+ * Translates the scope of dependencies when constructing a test bundle.
+ * Used by {@link Artifacts} to determine which artifacts that are provided by the runtime or must be included in the bundle.
+ *
+ * Dependencies of scope 'test' are by default translated to 'compile'. Dependencies of other scopes are kept as is.
+ *
+ * Default scope translation can be overridden through a comma-separated configuration string.
+ * Each substring is a triplet on the form [groupId]:[artifactId]:[scope].
+ * Scope translation overrides affects all transitive dependencies.
+ * The ordering of the triplets determines the priority - only the first matching override will affect a given dependency.
+ *
+ * @author bjorncs
+ */
+class TestBundleDependencyScopeTranslator implements Artifacts.ScopeTranslator {
+
+ private static final Logger log = Logger.getLogger(TestBundleDependencyScopeTranslator.class.getName());
+
+ private final Map<Artifact, String> dependencyScopes;
+
+ private TestBundleDependencyScopeTranslator(Map<Artifact, String> dependencyScopes) {
+ this.dependencyScopes = dependencyScopes;
+ }
+
+ @Override public String scopeOf(Artifact artifact) { return Objects.requireNonNull(dependencyScopes.get(artifact)); }
+
+ static TestBundleDependencyScopeTranslator from(Map<String, Artifact> dependencies, String rawConfig) {
+ List<DependencyOverride> dependencyOverrides = toDependencyOverrides(rawConfig);
+ Map<Artifact, String> dependencyScopes = new HashMap<>();
+ for (Artifact dependency : dependencies.values()) {
+ dependencyScopes.put(dependency, getScopeForDependency(dependency, dependencyOverrides, dependencies));
+ }
+ return new TestBundleDependencyScopeTranslator(dependencyScopes);
+ }
+
+ private static List<DependencyOverride> toDependencyOverrides(String rawConfig) {
+ if (rawConfig == null || rawConfig.isBlank()) return List.of();
+ return Arrays.stream(rawConfig.split(","))
+ .map(String::strip)
+ .filter(s -> !s.isBlank())
+ .map(TestBundleDependencyScopeTranslator::toDependencyOverride)
+ .collect(toList());
+ }
+
+ private static DependencyOverride toDependencyOverride(String overrideString) {
+ String[] elements = overrideString.split(":");
+ if (elements.length != 3) {
+ throw new IllegalArgumentException("Invalid dependency override: " + overrideString);
+ }
+ return new DependencyOverride(elements[0], elements[1], elements[2]);
+ }
+
+ private static String stripVersionAndScope(String idInDependencyTrail) {
+ int firstDelimiter = idInDependencyTrail.indexOf(':');
+ int secondDelimiter = idInDependencyTrail.indexOf(':', firstDelimiter + 1);
+ return idInDependencyTrail.substring(0, secondDelimiter);
+ }
+
+ private static String getScopeForDependency(
+ Artifact dependency, List<DependencyOverride> overrides, Map<String, Artifact> otherArtifacts) {
+ String oldScope = dependency.getScope();
+ for (DependencyOverride override : overrides) {
+ for (Artifact dependent : dependencyTrailOf(dependency, otherArtifacts)) {
+ if (override.isForArtifact(dependent)) {
+ // This translation is not always correct for artifacts having 'runtime' scope dependencies.
+ // If such dependencies are overridden to 'compile' scope, its 'runtime' dependencies will get
+ // scope 'compile' instead of 'runtime'.
+ log.fine(() -> String.format(
+ "Overriding scope of '%s'; scope '%s' overridden to '%s'",
+ dependency.getId(), oldScope, override.scope));
+ return override.scope;
+ }
+ }
+ }
+ String newScope = defaultScopeTranslationOf(oldScope);
+ log.fine(() -> String.format(
+ "Using default scope translation for '%s'; scope '%s' translated to '%s'",
+ dependency.getId(), oldScope, newScope));
+ return newScope;
+ }
+
+ private static List<Artifact> dependencyTrailOf(Artifact artifact, Map<String, Artifact> otherArtifacts) {
+ return artifact.getDependencyTrail().stream()
+ .skip(1) // Maven project itself is the first entry
+ .map(parentId -> otherArtifacts.get(stripVersionAndScope(parentId)))
+ .filter(Objects::nonNull)
+ .collect(toList());
+ }
+
+ private static String defaultScopeTranslationOf(String scope) {
+ return scope.equals(Artifact.SCOPE_TEST) ? Artifact.SCOPE_COMPILE : scope;
+ }
+
+ private static class DependencyOverride {
+ final String groupId;
+ final String artifactId;
+ final String scope;
+
+ DependencyOverride(String groupId, String artifactId, String scope) {
+ this.groupId = groupId;
+ this.artifactId = artifactId;
+ this.scope = scope;
+ }
+
+ boolean isForArtifact(Artifact artifact) {
+ return artifact.getGroupId().equals(groupId) && artifact.getArtifactId().equals(artifactId);
+ }
+ }
+}
diff --git a/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/TestProvidedArtifacts.java b/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/TestProvidedArtifacts.java
deleted file mode 100644
index e5a64744860..00000000000
--- a/bundle-plugin/src/main/java/com/yahoo/container/plugin/mojo/TestProvidedArtifacts.java
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.container.plugin.mojo;
-
-import org.apache.maven.artifact.Artifact;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.stream.Stream;
-
-import static java.util.stream.Collectors.toList;
-
-/**
- * Determines the test dependencies that are provided by the Vespa/JDisc test runtime based on the resolved dependency graph and a config string.
- * "Test provided" dependencies are treated as "provided" scope dependencies when building a test bundle.
- *
- * @author bjorncs
- */
-class TestProvidedArtifacts {
-
- private final List<Artifact> artifacts;
-
- private TestProvidedArtifacts(List<Artifact> artifacts) { this.artifacts = artifacts; }
-
- boolean isTestProvided(Artifact artifact) { return artifacts.contains(artifact); }
-
- static TestProvidedArtifacts from(Map<String, Artifact> artifacts, String configString) {
- if (configString == null || configString.isBlank()) return new TestProvidedArtifacts(List.of());
- return new TestProvidedArtifacts(getTestProvidedArtifacts(artifacts, configString));
- }
-
- private static List<Artifact> getTestProvidedArtifacts(Map<String, Artifact> artifacts, String configString) {
- List<String> testProvidedArtifactStringIds = toTestProvidedArtifactStringIds(configString);
- List<Artifact> testProvidedArtifacts = new ArrayList<>();
- for (Artifact artifact : artifacts.values()) {
- boolean hasTestProvidedArtifactAsParent =
- dependencyTrail(artifact, artifacts)
- .anyMatch(parent -> testProvidedArtifactStringIds.contains(toArtifactStringId(parent)));
- boolean isBlocked = testProvidedArtifactStringIds.contains(toBlockedArtifactStringId(artifact));
- if (hasTestProvidedArtifactAsParent && !isBlocked) {
- testProvidedArtifacts.add(artifact);
- }
- }
- return testProvidedArtifacts;
- }
-
- private static List<String> toTestProvidedArtifactStringIds(String commaSeparatedString) {
- if (commaSeparatedString == null || commaSeparatedString.isBlank()) return List.of();
- return Arrays.stream(commaSeparatedString.split(","))
- .map(String::strip)
- .filter(s -> !s.isBlank())
- .collect(toList());
- }
-
- private static Stream<Artifact> dependencyTrail(Artifact artifact, Map<String, Artifact> otherArtifacts) {
- return artifact.getDependencyTrail().stream()
- .map(parentId -> otherArtifacts.get(stripVersionAndScope(parentId)))
- .filter(Objects::nonNull);
- }
-
- private static String stripVersionAndScope(String fullArtifactIdentifier) {
- int firstDelimiter = fullArtifactIdentifier.indexOf(':');
- int secondDelimiter = fullArtifactIdentifier.indexOf(':', firstDelimiter + 1);
- return fullArtifactIdentifier.substring(0, secondDelimiter);
- }
-
- private static String toArtifactStringId(Artifact artifact) { return artifact.getGroupId() + ":" + artifact.getArtifactId(); }
-
- private static String toBlockedArtifactStringId(Artifact artifact) { return "!" + toArtifactStringId(artifact); }
-
-}