diff options
author | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2020-07-08 13:24:41 +0200 |
---|---|---|
committer | Bjørn Christian Seime <bjorncs@verizonmedia.com> | 2020-07-08 13:24:41 +0200 |
commit | 9b8f0756ecc1a038fbaab4388f74886965a5c02f (patch) | |
tree | cdcc27f7300017635ca200441a62106447fa5aae /bundle-plugin/src/main/java/com/yahoo/container/plugin/util | |
parent | 92e778cf7cb3a41c516becd4b2e8cf5cc295b865 (diff) |
Move helper classes from 'mojo' to 'util'
Diffstat (limited to 'bundle-plugin/src/main/java/com/yahoo/container/plugin/util')
3 files changed, 222 insertions, 0 deletions
diff --git a/bundle-plugin/src/main/java/com/yahoo/container/plugin/util/Artifacts.java b/bundle-plugin/src/main/java/com/yahoo/container/plugin/util/Artifacts.java new file mode 100644 index 00000000000..fc771e23fa7 --- /dev/null +++ b/bundle-plugin/src/main/java/com/yahoo/container/plugin/util/Artifacts.java @@ -0,0 +1,82 @@ +// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.container.plugin.util; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.project.MavenProject; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +/** + * @author Tony Vaagenes + * @author ollivir + */ +public class Artifacts { + interface ScopeTranslator { + String scopeOf(Artifact artifact); + } + + private static class NoopScopeTranslator implements ScopeTranslator { + @Override public String scopeOf(Artifact artifact) { return artifact.getScope(); } + } + + public static class ArtifactSet { + + private final List<Artifact> jarArtifactsToInclude; + private final List<Artifact> jarArtifactsProvided; + private final List<Artifact> nonJarArtifacts; + + private ArtifactSet( + List<Artifact> jarArtifactsToInclude, + List<Artifact> jarArtifactsProvided, + List<Artifact> nonJarArtifacts) { + this.jarArtifactsToInclude = jarArtifactsToInclude; + this.jarArtifactsProvided = jarArtifactsProvided; + this.nonJarArtifacts = nonJarArtifacts; + } + + public List<Artifact> getJarArtifactsToInclude() { + return jarArtifactsToInclude; + } + + public List<Artifact> getJarArtifactsProvided() { + return jarArtifactsProvided; + } + + public List<Artifact> getNonJarArtifacts() { + return nonJarArtifacts; + } + } + + public static ArtifactSet getArtifacts(MavenProject project) { return getArtifacts(project, new NoopScopeTranslator()); } + + public 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 (Artifact.SCOPE_COMPILE.equals(scope)) { + jarArtifactsToInclude.add(artifact); + } else if (Artifact.SCOPE_PROVIDED.equals(scope)) { + jarArtifactsProvided.add(artifact); + } + } else { + if (Artifact.SCOPE_COMPILE.equals(scope)) { + nonJarArtifactsToInclude.add(artifact); + } else if (Artifact.SCOPE_PROVIDED.equals(scope)) { + nonJarArtifactsProvided.add(artifact); + } + } + } + nonJarArtifactsToInclude.addAll(nonJarArtifactsProvided); + return new ArtifactSet(jarArtifactsToInclude, jarArtifactsProvided, nonJarArtifactsToInclude); + } + + public static Collection<Artifact> getArtifactsToInclude(MavenProject project) { + return getArtifacts(project, new NoopScopeTranslator()).getJarArtifactsToInclude(); + } +} diff --git a/bundle-plugin/src/main/java/com/yahoo/container/plugin/util/TestBundleDependencyScopeTranslator.java b/bundle-plugin/src/main/java/com/yahoo/container/plugin/util/TestBundleDependencyScopeTranslator.java new file mode 100644 index 00000000000..04ede59e2fe --- /dev/null +++ b/bundle-plugin/src/main/java/com/yahoo/container/plugin/util/TestBundleDependencyScopeTranslator.java @@ -0,0 +1,115 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.container.plugin.util; + +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 for 'test' scope dependencies 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 + */ +public 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)); } + + public 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(); + if (!oldScope.equals(Artifact.SCOPE_TEST)) return oldScope; + for (DependencyOverride override : overrides) { + for (Artifact dependent : dependencyTrailOf(dependency, otherArtifacts)) { + if (override.isForArtifact(dependent)) { + log.fine(() -> String.format( + "Overriding scope of '%s'; scope '%s' overridden to '%s'", + dependency.getId(), oldScope, override.scope)); + return override.scope; + } + } + } + log.fine(() -> String.format( + "Using default scope translation for '%s'; scope 'test' translated to 'compile'", + dependency.getId())); + return Artifact.SCOPE_COMPILE; + } + + 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 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/util/TestBundleUtils.java b/bundle-plugin/src/main/java/com/yahoo/container/plugin/util/TestBundleUtils.java new file mode 100644 index 00000000000..b8824952995 --- /dev/null +++ b/bundle-plugin/src/main/java/com/yahoo/container/plugin/util/TestBundleUtils.java @@ -0,0 +1,25 @@ +// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.container.plugin.util; + +import org.apache.maven.project.MavenProject; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.jar.JarFile; + +/** + * @author bjorncs + */ +public class TestBundleUtils { + private TestBundleUtils() {} + + public static Path outputDirectory(MavenProject project) { return targetDirectory(project).resolve("test-bundle/"); } + + public static Path manifestFile(MavenProject project) { return outputDirectory(project).resolve(JarFile.MANIFEST_NAME); } + + public static Path archiveFile(MavenProject project) { + return targetDirectory(project).resolve(project.getBuild().getFinalName() + "-tests.jar"); + } + + private static Path targetDirectory(MavenProject project) { return Paths.get(project.getBuild().getDirectory()); } +} |