Merge pull request #4631 from sdedic/project/artiacts-tags
Artifact tags, support for shaded output and source attachments.
diff --git a/ide/project.dependency/src/org/netbeans/modules/project/dependency/ArtifactSpec.java b/ide/project.dependency/src/org/netbeans/modules/project/dependency/ArtifactSpec.java
index 0bdc541..fb80df8 100644
--- a/ide/project.dependency/src/org/netbeans/modules/project/dependency/ArtifactSpec.java
+++ b/ide/project.dependency/src/org/netbeans/modules/project/dependency/ArtifactSpec.java
@@ -22,7 +22,10 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.Objects;
+import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.netbeans.api.annotations.common.NonNull;
@@ -45,10 +48,58 @@
* The version specified is further classified by {@link VersionKind}, to
* distinguish versions possibly from repositories, development versions and
* floating versions.
+ * <p>
+ * The ArtifactSpec may provide additional tags, that can further describe the artifact,
+ * but those tags are not part of "identity" of the artifact, for dependencies or build
+ * systems, only
+ * <ul>
+ * <li>group
+ * <li>artifact
+ * <li>version
+ * <li>classifier
+ * <Li>extension
+ * </ul>
+ * are important.
*
* @author sdedic
*/
public final class ArtifactSpec<T> {
+
+ /**
+ * A tag for an artifact with basic output of the project's code/contents.
+ * You almost never want this, usually you want {@code null} classifier to
+ * identify the <b>default</b> output. But in rare cases you really do want
+ * to avoid post-processing or shading, this (abstract) classifier should
+ * identify an artifact before those steps.
+ * <p>
+ * If used in a query, a non-tagged artifact may be returned if the implementation
+ * does not support the tag.
+ */
+ public static final String TAG_BASE = "<basic>"; // NOI18N
+
+ /**
+ * Tag for an artifact, that eventually contains dependencies bundled in. If used
+ * in a query, an ordinary (non-tagged) artifact may be returned from the query in case
+ * the implementation does not support the tag. Implementations may use additional, more
+ * specific tags on the returned artifacts.
+ */
+ public static final String TAG_SHADED = "<shaded>";
+
+ /**
+ * Classifier for an artifact that contains sources.
+ */
+ public static final String CLASSIFIER_SOURCES = "sources"; // NOI18N
+
+ /**
+ * Classifier for an artifact that contains test code
+ */
+ public static final String CLASSIFIER_TESTS = "tests"; // NOI18N
+
+ /**
+ * Classifier for an artifact that contains test sources.
+ */
+ public static final String CLASSIFIER_TEST_SOURCES = "test-sources"; // NOI18N
+
static final Logger LOG = Logger.getLogger(ProjectDependencies.class.getName());
/**
@@ -74,10 +125,14 @@
private final String classifier;
private final boolean optional;
private final URI location;
+
+ // note: tags is NOT a part of hascode / equals, as externally only the classifier
+ // is visible, e.g. to the build system.
+ private final Set<String> tags;
private FileObject localFile;
final T data;
- ArtifactSpec(VersionKind kind, String groupId, String artifactId, String versionSpec, String type, String classifier, boolean optional, URI location, FileObject localFile, T impl) {
+ ArtifactSpec(VersionKind kind, String groupId, String artifactId, String versionSpec, String type, String classifier, boolean optional, URI location, FileObject localFile, Set<String> tags, T impl) {
this.kind = kind;
this.groupId = groupId;
this.artifactId = artifactId;
@@ -88,6 +143,7 @@
this.type = type;
this.location = location;
this.localFile = localFile;
+ this.tags = tags == null ? Collections.emptySet() : tags;
}
public T getData() {
@@ -120,6 +176,10 @@
}
return f == FileUtil.getConfigRoot() ? null : f;
}
+
+ public boolean hasTag(String tag) {
+ return tags.contains(tag);
+ }
public URI getLocation() {
return location;
@@ -238,23 +298,25 @@
// should not happen
}
}
- return new ArtifactSpec<V>(VersionKind.REGULAR, groupId, artifactId, versionSpec, type, classifier, optional, uri, localFile, data);
+ return new ArtifactSpec<V>(VersionKind.REGULAR, groupId, artifactId, versionSpec, type, classifier, optional, uri, localFile, Collections.emptySet(), data);
}
public static <V> ArtifactSpec<V> createSnapshotSpec(
@NonNull String groupId, @NonNull String artifactId,
@NullAllowed String type, @NullAllowed String classifier,
@NonNull String versionSpec, boolean optional, @NullAllowed FileObject localFile, @NonNull V data) {
- URL u = URLMapper.findURL(localFile, URLMapper.EXTERNAL);
URI uri = null;
- if (u != null) {
- try {
- uri = u.toURI();
- } catch (URISyntaxException ex) {
- // should not happen
+ if (localFile != null) {
+ URL u = URLMapper.findURL(localFile, URLMapper.EXTERNAL);
+ if (u != null) {
+ try {
+ uri = u.toURI();
+ } catch (URISyntaxException ex) {
+ // should not happen
+ }
}
}
- return new ArtifactSpec<V>(VersionKind.SNAPSHOT, groupId, artifactId, versionSpec, type, classifier, optional, uri, localFile, data);
+ return new ArtifactSpec<V>(VersionKind.SNAPSHOT, groupId, artifactId, versionSpec, type, classifier, optional, uri, localFile, Collections.emptySet(), data);
}
public static final <T> Builder<T> builder(String group, String artifact, String version, T projectData) {
@@ -272,6 +334,7 @@
private boolean optional;
private FileObject localFile;
private URI location;
+ private Set<String> tags;
public Builder(String groupId, String artifactId, String versionSpec, T data) {
this.groupId = groupId;
@@ -299,6 +362,25 @@
this.localFile = localFile;
return this;
}
+
+ public Builder tag(String tag) {
+ if (tags == null) {
+ tags = new HashSet<>();
+ }
+ tags.add(tag);
+ return this;
+ }
+
+ public Builder tags(String... tags) {
+ if (tags == null || tags.length == 0) {
+ return this;
+ } else {
+ for (String t : tags) {
+ tag(t);
+ }
+ return this;
+ }
+ }
/**
* Forces the local file reference. Unlike {@link #localFile}, if {@code null} is
@@ -319,7 +401,7 @@
}
public ArtifactSpec build() {
- return new ArtifactSpec(kind, groupId, artifactId, versionSpec, type, classifier, optional, location, localFile, data);
+ return new ArtifactSpec(kind, groupId, artifactId, versionSpec, type, classifier, optional, location, localFile, tags, data);
}
}
}
diff --git a/ide/project.dependency/src/org/netbeans/modules/project/dependency/ProjectArtifactsQuery.java b/ide/project.dependency/src/org/netbeans/modules/project/dependency/ProjectArtifactsQuery.java
index f92840b..1d8a41b 100644
--- a/ide/project.dependency/src/org/netbeans/modules/project/dependency/ProjectArtifactsQuery.java
+++ b/ide/project.dependency/src/org/netbeans/modules/project/dependency/ProjectArtifactsQuery.java
@@ -19,9 +19,13 @@
package org.netbeans.modules.project.dependency;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.stream.Collectors;
@@ -43,7 +47,15 @@
* <p>
* By default the query will return artifacts produced by project's compilation (incl. packaging, in maven terminology) -
* but the exact meaning depends on a build system used, and the project's settings and the active configuration.
- *
+ * <p>
+ * Different project output are marked by different <b>classifiers</b>. Some special, abstract classifiers may
+ * be defined that should be handled by implementations specific for each build system.
+ * <ul>
+ * <li>{@link Filter#CLASSIFIER_BUNDLED} - describes a product with all dependencies included, such as the output of
+ * <b>shade or shadow plugins</b> in Gradle or Maven. Since the plugins behave differently (maven replaces the original artifact,
+ * while gradle attaches a new one), this meta-classiifer allows to pick the appropriate artifact despite its real classifier depends
+ * on project type. If there are more bundles (shadows),
+ * </ul>
* @author sdedic
*/
public final class ProjectArtifactsQuery {
@@ -140,6 +152,7 @@
List<ArtifactSpec> updateResults() {
boolean changes = false;
+ // accept only first matching artifact.
Collection<ArtifactSpec> specs = new LinkedHashSet<>();
for (E<?> e : delegates) {
Collection<ArtifactSpec> ex = e.findExcludedArtifacts();
@@ -213,25 +226,27 @@
* perhaps determined by the configured packaging with <b>no classifier</b>. It it possible
* to list artifacts of all types and/or artifacts with any classifier in one query.
*/
- public static class Filter {
+ public static final class Filter {
/**
* Represents all types of artifacts. The query will return all build products
*/
- public static final String TYPE_ALL = "all"; // NOI18N
+ public static final String TYPE_ALL = "<all>"; // NOI18N
/**
* Will return artifacts with any classifier.
*/
- public static final String CLASSIFIER_ANY = "any"; // NOI18N
+ public static final String CLASSIFIER_ANY = "<any>"; // NOI18N
+ private final Set<String> tags;
private final String classifier;
private final String artifactType;
private final ProjectActionContext buildContext;
- Filter(String artifactType, String classifier, ProjectActionContext buildContext) {
+ Filter(String artifactType, String classifier, Set<String> tags, ProjectActionContext buildContext) {
this.classifier = classifier;
this.artifactType = artifactType;
this.buildContext = buildContext;
+ this.tags = tags == null ? Collections.emptySet() : Collections.unmodifiableSet(tags);
}
/**
@@ -245,6 +260,14 @@
public String getClassifier() {
return classifier;
}
+
+ public Set<String> getTags() {
+ return tags;
+ }
+
+ public boolean hasTag(String t) {
+ return tags.contains(t);
+ }
/**
* The desired artifact type. Only artifacts with tha type will be returned. {@link #TYPE_ALL} means that artifacts
@@ -274,7 +297,7 @@
*/
@NonNull
public static Filter newQuery(@NullAllowed String artifactType) {
- return new Filter(artifactType, null, null);
+ return new Filter(artifactType, null, null, null);
}
/**
@@ -286,6 +309,20 @@
*/
@NonNull
public static Filter newQuery(@NullAllowed String artifactType, @NullAllowed String classifier, @NullAllowed ProjectActionContext buildContext) {
- return new Filter(artifactType, classifier, buildContext);
+ return new Filter(artifactType, classifier, null, buildContext);
+ }
+
+ /**
+ * Creates a Filter with the specified properties
+ * @param artifactType the desired type; use {@code null} for the default artifact type (i.e. defined by packaging)
+ * @param classifier the desired classifier; use {@code null} for no classifier
+ * @param buildContext the action context
+ * @return Filter instance.
+ */
+ @NonNull
+ public static Filter newQuery(@NullAllowed String artifactType, @NullAllowed String classifier, @NullAllowed ProjectActionContext buildContext, String... tags) {
+ return new Filter(artifactType, classifier,
+ tags == null || tags.length == 0 ? null : new HashSet<>(Arrays.asList(tags)),
+ buildContext);
}
}
diff --git a/ide/project.dependency/src/org/netbeans/modules/project/dependency/spi/ProjectArtifactsImplementation.java b/ide/project.dependency/src/org/netbeans/modules/project/dependency/spi/ProjectArtifactsImplementation.java
index 198350a..339cc78 100644
--- a/ide/project.dependency/src/org/netbeans/modules/project/dependency/spi/ProjectArtifactsImplementation.java
+++ b/ide/project.dependency/src/org/netbeans/modules/project/dependency/spi/ProjectArtifactsImplementation.java
@@ -41,7 +41,8 @@
public Result evaluate(ProjectArtifactsQuery.Filter query);
/**
- * Returns evaluation order of this Implementation. If the Implementation needs to post-process
+ * Returns evaluation order of this Implementation. Implementations ordered
+ * later may remove artifacts generated by earlier ones.
*
* @return
*/
diff --git a/java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/commands/ProjectMetadataCommand.java b/java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/commands/ProjectMetadataCommand.java
index 2cc483e..eabfd06 100644
--- a/java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/commands/ProjectMetadataCommand.java
+++ b/java/java.lsp.server/nbcode/integration/src/org/netbeans/modules/nbcode/integration/commands/ProjectMetadataCommand.java
@@ -22,6 +22,8 @@
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
@@ -132,7 +134,7 @@
public Set<String> getCommands() {
return COMMANDS;
}
-
+
@Override
public CompletableFuture<Object> processCommand(NbCodeLanguageClient client, String command, List<Object> arguments) {
if (arguments.size() < 1) {
@@ -140,29 +142,79 @@
}
FileObject f = Utils.extractFileObject(arguments.get(0), gson);
Project p = FileOwnerQuery.getOwner(f);
- if (p == null || p.getProjectDirectory() != f) {
+ if (p == null) {
throw new IllegalArgumentException("Not a project " + f);
}
String artifactType = null;
ProjectActionContext ctx = null;
+ String[] tags = null;
+ String classifier = null;
if (arguments.size() > 1) {
// 2nd parameter is the project action
Object o = arguments.get(1);
- if (!(o instanceof JsonPrimitive)) {
- throw new IllegalArgumentException("String or null expected as parameter #3, got " + o);
+ if (o instanceof JsonObject) {
+ JsonObject request = (JsonObject)o;
+ if (request.has("action")) {
+ Object a = request.get("action");
+ if (a instanceof JsonPrimitive) {
+ ctx = ProjectActionContext.newBuilder(p).forProjectAction(((JsonPrimitive)a).getAsString()).context();
+ } else {
+ throw new IllegalArgumentException("String expected as action, got " + a);
+ }
+ }
+ if (request.has("type")) {
+ Object t = request.get("type");
+ if (t instanceof JsonPrimitive) {
+ artifactType = ((JsonPrimitive)t).getAsString();
+ } else {
+ throw new IllegalArgumentException("String expected as type, got " + t);
+ }
+ }
+ if (request.has("classifier")) {
+ Object c = request.get("classifier");
+ if (c instanceof JsonPrimitive) {
+ classifier = ((JsonPrimitive)c).getAsString();
+ } else {
+ throw new IllegalArgumentException("String expected as classifier, got " + c);
+ }
+ }
+ if (request.has("tags")) {
+ Object t = request.get("tags");
+ if (t instanceof JsonPrimitive) {
+ tags = new String[] { ((JsonPrimitive)t).getAsString() };
+ } else if (t instanceof JsonArray) {
+ JsonArray arr = (JsonArray)t;
+ tags = new String[arr.size()];
+ int index = 0;
+ for (Object item : arr) {
+ if (item instanceof JsonPrimitive) {
+ tags[index++] = ((JsonPrimitive)item).getAsString();
+ } else {
+ throw new IllegalArgumentException("String expected as tag, got " + item);
+ }
+ }
+ } else {
+ throw new IllegalArgumentException("String or array expected as tags, got " + t);
+ }
+ }
+
+ } else if (o instanceof JsonPrimitive) {
+ ctx = ProjectActionContext.newBuilder(p).forProjectAction(((JsonPrimitive)o).getAsString()).context();
+ } else {
+ throw new IllegalArgumentException("String, structure, or null expected as parameter #2, got " + o);
}
- ctx = ProjectActionContext.newBuilder(p).forProjectAction(((JsonPrimitive)o).getAsString()).context();
+
}
if (arguments.size() > 2) {
// 3rd parameter is the type of artifact
Object o = arguments.get(2);
if (!(o instanceof JsonPrimitive)) {
- throw new IllegalArgumentException("String or null expected as parameter #2, got " + o);
+ throw new IllegalArgumentException("String or null expected as parameter #3, got " + o);
}
artifactType = ((JsonPrimitive)o).getAsString();
}
- ProjectArtifactsQuery.Filter filter = ProjectArtifactsQuery.newQuery(artifactType, null, ctx);
+ ProjectArtifactsQuery.Filter filter = ProjectArtifactsQuery.newQuery(artifactType, classifier, ctx, tags);
CompletableFuture result = new CompletableFuture();
METADATA_PROCESSOR.post(() -> {
try {
diff --git a/java/maven/src/org/netbeans/modules/maven/queries/MavenArtifactsImplementation.java b/java/maven/src/org/netbeans/modules/maven/queries/MavenArtifactsImplementation.java
index 8a6bfd1..b3fc45d 100644
--- a/java/maven/src/org/netbeans/modules/maven/queries/MavenArtifactsImplementation.java
+++ b/java/maven/src/org/netbeans/modules/maven/queries/MavenArtifactsImplementation.java
@@ -59,8 +59,9 @@
*/
@ProjectServiceProvider(service = ProjectArtifactsImplementation.class, projectType = NbMavenProject.TYPE)
public class MavenArtifactsImplementation implements ProjectArtifactsImplementation<MavenArtifactsImplementation.Res> {
+
private static final Logger LOG = Logger.getLogger(ProjectArtifactsImplementation.class.getName());
-
+
private final Project project;
public MavenArtifactsImplementation(Project project) {
@@ -129,27 +130,293 @@
public boolean computeSupportsChanges(Res r) {
return r.supportsChanges();
}
-
+
static class MavenQuery {
+
final Project project;
final NbMavenProject nbMavenProject;
final ProjectArtifactsQuery.Filter filter;
-
+ MavenProject evalProject;
+
List<ArtifactSpec> specs;
+
+ boolean skipDefaultOutput;
public MavenQuery(Project project, NbMavenProject nbMavenProject, ProjectArtifactsQuery.Filter filter) {
this.project = project;
this.nbMavenProject = nbMavenProject;
this.filter = filter;
}
+
+ void addArtifactSpec(ArtifactSpec spec) {
+ if (specs.contains(spec)) {
+ return;
+ }
+ specs.add(spec);
+ }
+
+ /**
+ * Evaluator that processes one execution of the shade plugin. Note that multiple artifacts may be produced in multiple
+ * executions, with different classifiers.
+ */
+ private class ShadedEvaluator {
+ /**
+ * Default classifier for attached artifacts produced by shade plugin
+ */
+ private static final String DEFAULT_SHADE_CLASSIFIER = "shaded";
+
+ private final MavenProject evalProject;
+ private final PluginExecution exec;
+ private String t;
+ private String c;
+
+ String classifier;
+ String outputDir;
+ String outputFile;
+ String finalName;
+ String artifactId;
+ boolean attached;
+ boolean createSourcesJar;
+ boolean createTestJar;
+ boolean createTestSourcesJar;
+ String outD;
+ String name;
+ Path basePath;
+ Artifact mA;
+ boolean any;
+ boolean tagBase;
+ boolean tagShaded;
+ boolean renamed;
+
+ public ShadedEvaluator(MavenProject evalProject, PluginExecution exec) {
+ this.evalProject = evalProject;
+ this.exec = exec;
+ }
+
+ public void process() {
+ Xpp3Dom dom = evalProject.getGoalConfiguration(
+ Constants.GROUP_APACHE_PLUGINS, "maven-shade-plugin", exec.getId(), "shade"); // NOI18N
+ mA = evalProject.getArtifact();
+ t = filter.getArtifactType();
+ c = filter.getClassifier();
+ classifier = getValueOrNull(dom, "shadedClassifierName"); // NOI18N
+ outputDir = getValueOrNull(dom, "outputDirectory"); // NOI18N
+ outputFile = getValueOrNull(dom, "outputFile"); // NOI18N
+ finalName = getValueOrNull(dom, "finalName"); // NOI18N
+ artifactId = getValueOrNull(dom, "shadedArtifactId"); // NOI18N
+
+ attached = Boolean.valueOf(getValueOrNull(dom, "shadedArtifactAttached")); // NOI18N
+ createSourcesJar = Boolean.valueOf(getValueOrNull(dom, "createSourcesJar")); // NOI18N
+ createTestJar = Boolean.valueOf(getValueOrNull(dom, "shadeTestJar")); // NOI18N
+ createTestSourcesJar = Boolean.valueOf(getValueOrNull(dom, "createTestSourcesJar")); // NOI18N
+
+ outD = evalProject.getModel().getBuild().getDirectory();
+ name = evalProject.getBuild().getFinalName();
+
+ if (artifactId == null) {
+ artifactId = mA.getArtifactId();
+ }
+
+ if (outputDir != null) {
+ outD = outputDir;
+ }
+ if (finalName != null && finalName.length() > 0) {
+ name = finalName;
+ }
+ basePath = Paths.get(outD, name);
+ any = ProjectArtifactsQuery.Filter.CLASSIFIER_ANY.equals(c);
+
+ tagShaded = filter.hasTag(ArtifactSpec.TAG_SHADED) || filter.hasTag(classifier);
+ tagBase = filter.hasTag(ArtifactSpec.TAG_BASE);
+
+ // either the caller selects the classifier, or no classifier (this produces artifact tagged with 'shaded' or
+ // explicitly tagged with original to get the unshaded version
+ if (attached) {
+ if (classifier == null) {
+ classifier = DEFAULT_SHADE_CLASSIFIER;
+ }
+ }
+ boolean classifierMatch = any || (classifier != null && classifier.equals(c)) || (c == null && !attached) || tagBase;
+ String suffix;
+
+ String gID = mA.getGroupId();
+ if (outputFile != null) {
+ addExplicitOutputFile();
+ suffix = "-" + classifier;
+ } else {
+ if (name != null && !name.equals(evalProject.getBuild().getFinalName())) {
+ renamed = true;
+ basePath = basePath.resolveSibling(name);
+ suffix = "";
+ } else {
+ suffix = "";
+ }
+ if (attached) {
+ suffix = "-" + classifier;
+ }
+ if (classifierMatch) {
+ // do not report base unless the base is explicitly requested
+ if ((any && !tagShaded) || tagBase) {
+ skipDefaultOutput = !attached;
+ Path file = basePath.resolveSibling("original-" + basePath.getFileName() + suffix + ".jar");
+ ArtifactSpec spec = ArtifactSpec.builder(attached ? gID : null, attached ? artifactId : null, mA.getVersion(), evalProject).
+ classifier(classifier).
+ location(file.toUri()).
+ type("jar").
+ tag(ArtifactSpec.TAG_BASE).
+ build();
+ addArtifactSpec(spec);
+ }
+ boolean reportShaded;
+ if (any) {
+ reportShaded = !tagBase || tagShaded;
+ } else {
+ // if no tag is present the default is to report the shaded artifact
+ reportShaded = !tagBase;
+ }
+ if (reportShaded) {
+ Path file = basePath.resolveSibling(basePath.getFileName() + suffix + ".jar");
+ ArtifactSpec spec = ArtifactSpec.builder(gID, artifactId, mA.getVersion(), evalProject).
+ classifier(classifier).
+ location(file.toUri()).
+ type("jar").
+ tag(ArtifactSpec.TAG_SHADED).
+ build();
+ addArtifactSpec(spec);
+ }
+ }
+ }
+
+ if (classifierMatch) {
+ if (createSourcesJar) {
+ addClassifiedArtifact("sources", suffix, "sources", ArtifactSpec.CLASSIFIER_SOURCES, "java-source");
+ }
+ if (createTestJar) {
+ addClassifiedArtifact("test-jar", suffix, "tests", ArtifactSpec.CLASSIFIER_TESTS, "test");
+ }
+ if (createTestSourcesJar) {
+ addClassifiedArtifact("sources", suffix, "test-sources", ArtifactSpec.CLASSIFIER_TEST_SOURCES, "java-source", "test");
+ }
+ }
+ }
+
+ private void addClassifiedArtifact(String type, String suffix, String typeSuffix, String defaultClassifier, String... tags) {
+ if (!(ProjectArtifactsQuery.Filter.TYPE_ALL.equals(t) || type.equals(t) || (any && t == null))) {
+ return;
+ }
+
+ Path file;
+ ArtifactSpec spec;
+
+ String clas = classifier;
+ if (clas == null) {
+ clas = defaultClassifier;
+ }
+
+ if (any || !tagBase || tagShaded) {
+ file = basePath.resolveSibling(basePath.getFileName() + suffix + "-" + typeSuffix + ".jar");
+ spec = ArtifactSpec.builder(mA.getGroupId(), artifactId, mA.getVersion(), evalProject).
+ classifier(clas).
+ location(file.toUri()).
+ type(type).
+ tag(ArtifactSpec.TAG_SHADED).
+ tags(tags).
+ build();
+ addArtifactSpec(spec);
+ }
+
+ if (any || tagBase) {
+ file = basePath.resolveSibling("original-" + basePath.getFileName() + suffix + "-" + typeSuffix + ".jar");
+ spec = ArtifactSpec.builder(attached ? mA.getGroupId() : null, attached ? artifactId : null, mA.getVersion(), evalProject).
+ classifier(clas).
+ location(file.toUri()).
+ type(type).
+ tag(ArtifactSpec.TAG_BASE).
+ tags(tags).
+ build();
+ addArtifactSpec(spec);
+ }
+ }
+
+ /**
+ * Include only if shaded was explicitly requested, or ALL
+ * classifiers. Otherwise the shaded artifact does not replace the
+ * main artifact and is not 'officially' attached, so it should be
+ * probably not reported at all, as it is invisible outside the
+ * project.
+ */
+ void addExplicitOutputFile() {
+ if ((ProjectArtifactsQuery.Filter.TYPE_ALL.equals(t) || t == null || "jar".equals(t))
+ && (any || (c == null && filter.hasTag(ArtifactSpec.TAG_SHADED)))) {
+ Path file = null;
+ try {
+ file = Paths.get(outputFile);
+ ArtifactSpec spec = ArtifactSpec.builder(null, null, mA.getVersion(), evalProject).
+ classifier(classifier).
+ location(file.toUri()).
+ type("jar").
+ tag(ArtifactSpec.TAG_SHADED).
+ build();
+ addArtifactSpec(spec);
+ } catch (InvalidPathException ex) {
+ // no main artifact produced.
+ }
+ } else {
+
+ }
+ if ((ProjectArtifactsQuery.Filter.TYPE_ALL.equals(t) || t == null || "jar".equals(t))
+ && (any || (c == null && (filter.hasTag(ArtifactSpec.TAG_BASE) || filter.hasTag(DEFAULT_SHADE_CLASSIFIER))))) {
+ // include the original, but tag it with base
+ Path p = basePath.resolveSibling("original-" + basePath.getFileName() + ".jar"); // NOI18N
+ ArtifactSpec spec = ArtifactSpec.builder(null, null, mA.getVersion(), evalProject).
+ classifier(classifier).
+ location(p.toUri()).
+ type("jar").
+ tag(ArtifactSpec.TAG_BASE).
+ build();
+ addArtifactSpec(spec);
+ }
+ // the other possible attachments are not afffected by 'outputFile'
+ }
+
+ }
+
+ private void appendShadePluginOutput(MavenProject evalProject) {
+ Plugin plugin = evalProject.getBuild().getPluginsAsMap().get(Constants.GROUP_APACHE_PLUGINS + ":" + "maven-shade-plugin"); // NOI18N
+ if (plugin == null) {
+ return;
+ }
+ for (PluginExecution exec : plugin.getExecutions()) {
+ if (exec.getGoals().contains("shade")) {
+ ShadedEvaluator shadedEval = new ShadedEvaluator(evalProject, exec);
+ shadedEval.process();
+ }
+ }
+ }
+
+ private static String getValueOrNull(Xpp3Dom parent, String childName) {
+ return getChildValue(parent, childName, null);
+ }
+
+ private static String getChildValue(Xpp3Dom parent, String childName, String defValue) {
+ Xpp3Dom child = null;
+ if (parent != null) {
+ child = parent.getChild(childName);
+ }
+ return child != null ? child.getValue() : defValue;
+ }
private void appendPluginOutput(MavenProject evalProject, String pluginId, String goal, String packagingAndType) {
+ appendPluginOutput(evalProject, pluginId, goal, packagingAndType, packagingAndType, null);
+ }
+
+ private void appendPluginOutput(MavenProject evalProject, String pluginId, String goal, String type, String packaging, String defaultClassifier, String... tags) {
if (filter != null) {
if (filter.getArtifactType() == null) {
- if (!evalProject.getPackaging().equals(packagingAndType)) {
+ if (!evalProject.getPackaging().equals(packaging)) {
return;
}
- } else if (!filter.getArtifactType().equals(packagingAndType)) {
+ } else if (!filter.getArtifactType().equals(type)) {
if (!ProjectArtifactsQuery.Filter.TYPE_ALL.equals(filter.getArtifactType())) {
return;
}
@@ -157,12 +424,12 @@
}
Artifact mA = evalProject.getArtifact();
Model mdl = evalProject.getModel();
-
+
Plugin plugin = evalProject.getBuild().getPluginsAsMap().get(Constants.GROUP_APACHE_PLUGINS + ":" + pluginId); // NOI18N
if (plugin == null) {
return;
}
-
+
for (PluginExecution exec : plugin.getExecutions()) {
if (exec.getGoals().contains(goal)) {
Xpp3Dom dom = evalProject.getGoalConfiguration(
@@ -171,6 +438,9 @@
Xpp3Dom domOutputDir = dom == null ? null : dom.getChild("outputDirectory"); // NOI18N
String classifier = domClassifier == null ? null : domClassifier.getValue();
+ if (classifier == null) {
+ classifier = defaultClassifier;
+ }
if (filter != null && !ProjectArtifactsQuery.Filter.CLASSIFIER_ANY.equals(filter.getClassifier())) {
if (!Objects.equals(classifier, filter.getClassifier())) {
@@ -178,15 +448,16 @@
}
}
StringBuilder finalNameExt = new StringBuilder(mdl.getBuild().getFinalName());
- if (domClassifier != null) {
- finalNameExt.append("-").append(domClassifier.getValue());
+ if (classifier != null) {
+ finalNameExt.append("-").append(classifier);
}
- finalNameExt.append(".").append(packagingAndType);
+ finalNameExt.append(".").append(packaging);
- ArtifactSpec.Builder builder = ArtifactSpec.builder(mA.getGroupId(), mA.getArtifactId(), mA.getVersion(),
+ ArtifactSpec.Builder builder = ArtifactSpec.builder(mA.getGroupId(), mA.getArtifactId(), mA.getVersion(),
nbMavenProject.getMavenProject().getArtifact())
.classifier(classifier)
- .type(packagingAndType);
+ .tags(tags)
+ .type(type);
try {
Path dir = Paths.get(mdl.getBuild().getDirectory());
if (domOutputDir != null) {
@@ -202,16 +473,16 @@
} catch (InvalidPathException ex) {
// TODO: log
}
- specs.add(builder.build());
+ addArtifactSpec(builder.build());
}
}
}
-
+
public void run() {
specs = new ArrayList<>();
Model mdl;
ProjectActionContext buildCtx;
-
+
if (filter != null && filter.getBuildContext() != null) {
if (filter.getBuildContext().getProjectAction() == null) {
buildCtx = filter.getBuildContext().newDerivedBuilder().forProjectAction(ActionProvider.COMMAND_BUILD).context();
@@ -223,37 +494,47 @@
}
MavenProject mp = nbMavenProject.getEvaluatedProject(buildCtx);
mdl = mp.getModel();
-
+ evalProject = mp;
+
String packaging = mdl.getPackaging();
if (packaging == null) {
packaging = NbMavenProject.TYPE_JAR;
}
- appendPluginOutput(mp, Constants.PLUGIN_JAR, NbMavenProject.TYPE_JAR, NbMavenProject.TYPE_JAR);
+ appendShadePluginOutput(evalProject);
+
+ if (!skipDefaultOutput) {
+ appendPluginOutput(mp, Constants.PLUGIN_JAR, NbMavenProject.TYPE_JAR, NbMavenProject.TYPE_JAR);
+ }
+ appendPluginOutput(mp, Constants.PLUGIN_JAR, "test-jar", "test-jar", NbMavenProject.TYPE_JAR, ArtifactSpec.CLASSIFIER_TESTS);
+ appendPluginOutput(mp, "maven-source-plugin", "jar", "sources", NbMavenProject.TYPE_JAR, ArtifactSpec.CLASSIFIER_SOURCES, "java-source");
+ appendPluginOutput(mp, "maven-source-plugin", "test-jar", "sources", NbMavenProject.TYPE_JAR, ArtifactSpec.CLASSIFIER_TEST_SOURCES, "java-source", "test");
+
appendPluginOutput(mp, Constants.PLUGIN_WAR, NbMavenProject.TYPE_WAR, NbMavenProject.TYPE_WAR);
appendPluginOutput(mp, Constants.PLUGIN_EAR, NbMavenProject.TYPE_EAR, NbMavenProject.TYPE_EAR);
appendPluginOutput(mp, Constants.PLUGIN_EJB, NbMavenProject.TYPE_EJB, NbMavenProject.TYPE_EJB);
}
}
-
+
private static final RequestProcessor MAVEN_ARTIFACTS_RP = new RequestProcessor(MavenArtifactsImplementation.class);
static class Res implements PropertyChangeListener {
+
private final Project project;
private final ProjectArtifactsQuery.Filter filter;
-
+
// @GuardedBy(this)
private List<ArtifactSpec> artifacts;
// @GuardedBy(this)
private List<ChangeListener> listeners;
-
+
private RequestProcessor.Task refreshTask;
-
+
public Res(Project project, ProjectArtifactsQuery.Filter filter) {
this.project = project;
this.filter = filter;
}
-
+
public Project getProject() {
return project;
}
@@ -274,12 +555,12 @@
}
return q.specs;
}
-
+
private void update(List<ArtifactSpec> copy, RequestProcessor.Task self) {
NbMavenProject mvnProject = project.getLookup().lookup(NbMavenProject.class);
MavenQuery q = new MavenQuery(project, mvnProject, filter);
q.run();
-
+
ChangeListener[] ll;
synchronized (this) {
if (artifacts == null) {
@@ -296,7 +577,7 @@
l.stateChanged(e);
}
}
-
+
public Collection<ArtifactSpec> getExcludedArtifacts() {
return null;
}
@@ -327,7 +608,7 @@
}
ChangeListener[] ll;
final List<ArtifactSpec> copy;
-
+
synchronized (this) {
artifacts = null;
if (listeners == null && listeners.isEmpty()) {
@@ -338,9 +619,9 @@
}
copy = artifacts == null ? Collections.emptyList() : new ArrayList<>(this.artifacts);
RequestProcessor.Task[] arr = new RequestProcessor.Task[1];
-
+
arr[0] = refreshTask = MAVEN_ARTIFACTS_RP.create(() -> update(copy, arr[0]));
-
+
ll = listeners.toArray(new ChangeListener[listeners.size()]);
}
ChangeEvent e = new ChangeEvent(this);
diff --git a/java/maven/test/unit/data/artifacts/shaded-attached/pom.xml b/java/maven/test/unit/data/artifacts/shaded-attached/pom.xml
new file mode 100644
index 0000000..281dd69
--- /dev/null
+++ b/java/maven/test/unit/data/artifacts/shaded-attached/pom.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>nbtest.grp</groupId>
+ <artifactId>shaded-attached</artifactId>
+ <version>16</version>
+
+ <name>Shaded Test</name>
+ <description>Tests artifacts from shade plugin</description>
+
+ <properties>
+ <maven.compiler.source>1.8</maven.compiler.source>
+ <maven.compiler.target>1.8</maven.compiler.target>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.7.36</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-jdk14</artifactId>
+ <version>1.7.36</version>
+ <scope>runtime</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <version>3.3.0</version>
+ <configuration>
+ <shadedArtifactAttached>true</shadedArtifactAttached>
+ </configuration>
+ <executions>
+ <execution>
+ <id>default-shade</id>
+ <phase>package</phase>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
+
diff --git a/java/maven/test/unit/data/artifacts/shaded-attached/src/main/java/SampleApplication.java b/java/maven/test/unit/data/artifacts/shaded-attached/src/main/java/SampleApplication.java
new file mode 100644
index 0000000..0db334b
--- /dev/null
+++ b/java/maven/test/unit/data/artifacts/shaded-attached/src/main/java/SampleApplication.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ *
+ * @author sdedic
+ */
+public class SampleApplication {
+
+}
diff --git a/java/maven/test/unit/data/artifacts/shaded-default/pom.xml b/java/maven/test/unit/data/artifacts/shaded-default/pom.xml
new file mode 100644
index 0000000..f836baf
--- /dev/null
+++ b/java/maven/test/unit/data/artifacts/shaded-default/pom.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>nbtest.grp</groupId>
+ <artifactId>shaded-default</artifactId>
+ <version>16</version>
+
+ <name>Shaded Test</name>
+ <description>Tests artifacts from shade plugin</description>
+
+ <properties>
+ <maven.compiler.source>1.8</maven.compiler.source>
+ <maven.compiler.target>1.8</maven.compiler.target>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.7.36</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-jdk14</artifactId>
+ <version>1.7.36</version>
+ <scope>runtime</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <version>3.3.0</version>
+ <executions>
+ <execution>
+ <id>default-shade</id>
+ <phase>package</phase>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
+
diff --git a/java/maven/test/unit/data/artifacts/shaded-default/src/main/java/SampleApplication.java b/java/maven/test/unit/data/artifacts/shaded-default/src/main/java/SampleApplication.java
new file mode 100644
index 0000000..0db334b
--- /dev/null
+++ b/java/maven/test/unit/data/artifacts/shaded-default/src/main/java/SampleApplication.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ *
+ * @author sdedic
+ */
+public class SampleApplication {
+
+}
diff --git a/java/maven/test/unit/data/artifacts/shaded-sources/pom.xml b/java/maven/test/unit/data/artifacts/shaded-sources/pom.xml
new file mode 100644
index 0000000..d0aa1ca
--- /dev/null
+++ b/java/maven/test/unit/data/artifacts/shaded-sources/pom.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>nbtest.grp</groupId>
+ <artifactId>shaded-sources</artifactId>
+ <version>16</version>
+
+ <name>Shaded Test</name>
+ <description>Tests artifacts from shade plugin</description>
+
+ <properties>
+ <maven.compiler.source>1.8</maven.compiler.source>
+ <maven.compiler.target>1.8</maven.compiler.target>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.7.36</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-jdk14</artifactId>
+ <version>1.7.36</version>
+ <scope>runtime</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>3.2.1</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>jar</goal>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>3.2.2</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <version>3.3.0</version>
+ <configuration>
+ <shadeTestJar>true</shadeTestJar>
+ <createSourcesJar>true</createSourcesJar>
+ <createTestSourcesJar>true</createTestSourcesJar>
+ </configuration>
+ <executions>
+ <execution>
+ <id>default-shade</id>
+ <phase>package</phase>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
+
diff --git a/java/maven/test/unit/data/artifacts/shaded-sources/src/main/java/SampleApplication.java b/java/maven/test/unit/data/artifacts/shaded-sources/src/main/java/SampleApplication.java
new file mode 100644
index 0000000..0db334b
--- /dev/null
+++ b/java/maven/test/unit/data/artifacts/shaded-sources/src/main/java/SampleApplication.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ *
+ * @author sdedic
+ */
+public class SampleApplication {
+
+}
diff --git a/java/maven/test/unit/data/artifacts/sources/pom.xml b/java/maven/test/unit/data/artifacts/sources/pom.xml
new file mode 100644
index 0000000..dbf3dd3
--- /dev/null
+++ b/java/maven/test/unit/data/artifacts/sources/pom.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>nbtest.grp</groupId>
+ <artifactId>sources</artifactId>
+ <version>16</version>
+
+ <name>Shaded Test</name>
+ <description>Tests artifacts from shade plugin</description>
+
+ <properties>
+ <maven.compiler.source>1.8</maven.compiler.source>
+ <maven.compiler.target>1.8</maven.compiler.target>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.7.36</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-jdk14</artifactId>
+ <version>1.7.36</version>
+ <scope>runtime</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>3.2.1</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>jar</goal>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>3.2.2</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <!--
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <version>3.3.0</version>
+ <configuration>
+ <shadeTestJar>true</shadeTestJar>
+ <createSourcesJar>true</createSourcesJar>
+ <createTestSourcesJar>true</createTestSourcesJar>
+ </configuration>
+ <executions>
+ <execution>
+ <id>default-shade</id>
+ <phase>package</phase>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ -->
+ </plugins>
+ </build>
+</project>
+
diff --git a/java/maven/test/unit/data/artifacts/sources/src/main/java/SampleApplication.java b/java/maven/test/unit/data/artifacts/sources/src/main/java/SampleApplication.java
new file mode 100644
index 0000000..0db334b
--- /dev/null
+++ b/java/maven/test/unit/data/artifacts/sources/src/main/java/SampleApplication.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ *
+ * @author sdedic
+ */
+public class SampleApplication {
+
+}
diff --git a/java/maven/test/unit/src/org/netbeans/modules/maven/queries/MavenArtifactsImplementationTest.java b/java/maven/test/unit/src/org/netbeans/modules/maven/queries/MavenArtifactsImplementationTest.java
index 5837fb0..c7de3ac 100644
--- a/java/maven/test/unit/src/org/netbeans/modules/maven/queries/MavenArtifactsImplementationTest.java
+++ b/java/maven/test/unit/src/org/netbeans/modules/maven/queries/MavenArtifactsImplementationTest.java
@@ -20,6 +20,8 @@
import java.io.File;
import java.net.URI;
+import java.nio.file.Paths;
+import java.util.List;
import java.util.concurrent.Exchanger;
import static junit.framework.TestCase.assertNotNull;
import static junit.framework.TestCase.assertNull;
@@ -27,7 +29,6 @@
import org.netbeans.api.project.ProjectActionContext;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.junit.NbTestCase;
-import org.netbeans.modules.maven.api.Constants;
import org.netbeans.modules.maven.api.NbMavenProject;
import org.netbeans.modules.maven.embedder.EmbedderFactory;
import org.netbeans.modules.project.dependency.ArtifactSpec;
@@ -291,4 +292,357 @@
assertEquals(0, ar.getArtifacts().size());
}
+ /**
+ * Checks that the default artifact for shaded plugin does not change, but is annotated
+ * by an appropriate tag.
+ */
+ public void testShadedDefault() throws Exception {
+ FileObject testApp = dataFO.getFileObject("artifacts/shaded-default/");
+ FileObject prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "shaded-default");
+
+ Project p = ProjectManager.getDefault().findProject(prjCopy);
+ ProjectArtifactsQuery.ArtifactsResult ar = ProjectArtifactsQuery.findArtifacts(p,
+ ProjectArtifactsQuery.newQuery(NbMavenProject.TYPE_JAR)
+ );
+
+ assertNotNull(ar);
+ List<ArtifactSpec> specs = ar.getArtifacts();
+ assertEquals(1, specs.size());
+
+ ArtifactSpec uberJar = specs.get(0);
+ assertReplacementUberjar(uberJar);
+ }
+
+ /**
+ * Checks that the original jar can be queried, but has no GAV.
+ */
+ public void testShadedDefaultOriginal() throws Exception {
+ FileObject testApp = dataFO.getFileObject("artifacts/shaded-default/");
+ FileObject prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "shaded-default");
+
+ Project p = ProjectManager.getDefault().findProject(prjCopy);
+ ProjectArtifactsQuery.ArtifactsResult ar = ProjectArtifactsQuery.findArtifacts(p,
+ ProjectArtifactsQuery.newQuery(NbMavenProject.TYPE_JAR, null, null, ArtifactSpec.TAG_BASE)
+ );
+
+ List<ArtifactSpec> specs = ar.getArtifacts();
+ assertEquals(1, specs.size());
+ ArtifactSpec origJar = specs.get(0);
+ assertNotAttachedOriginal(origJar);
+ }
+
+ private void assertReplacementUberjar(ArtifactSpec uberJar) {
+ assertReplacementUberjar(uberJar, "shaded-default");
+ }
+
+ private void assertReplacementUberjar(ArtifactSpec uberJar, String prjName) {
+ assertEquals("Uber-jar has a proper artifactId", prjName, uberJar.getArtifactId());
+ assertEquals("Uber-jar has a proper groupId", "nbtest.grp", uberJar.getGroupId());
+ assertNull("Uber-jar should have no classifier", uberJar.getClassifier());
+ assertTrue(uberJar.hasTag("<shaded>"));
+ assertFalse(uberJar.hasTag(ArtifactSpec.TAG_BASE));
+ }
+
+ void assertNotAttachedOriginal(ArtifactSpec origJar) {
+ assertNull("Orig-jar has no artifactId", origJar.getArtifactId());
+ assertNull("Orig-jar has no groupId", origJar.getGroupId());
+ assertNull("Orig-jar should have no classifier", origJar.getClassifier());
+ assertTrue(origJar.hasTag(ArtifactSpec.TAG_BASE));
+ assertFalse(origJar.hasTag("<shaded>"));
+ }
+
+ /**
+ * Checks that 'any classifier' produces all jars, original and shaded.
+ */
+ public void testShadedAllCodeJars() throws Exception {
+ FileObject testApp = dataFO.getFileObject("artifacts/shaded-default/");
+ FileObject prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "shaded-default");
+
+ Project p = ProjectManager.getDefault().findProject(prjCopy);
+ ProjectArtifactsQuery.ArtifactsResult ar = ProjectArtifactsQuery.findArtifacts(p,
+ ProjectArtifactsQuery.newQuery(NbMavenProject.TYPE_JAR, ProjectArtifactsQuery.Filter.CLASSIFIER_ANY, null)
+ );
+ List<ArtifactSpec> specs = ar.getArtifacts();
+ assertEquals(2, specs.size());
+
+ boolean shadedFound = false;
+ boolean origFound = false;
+ for (ArtifactSpec spec : specs) {
+ if (spec.hasTag(ArtifactSpec.TAG_BASE)) {
+ assertFalse("Single base artifact expected", origFound);
+ origFound = true;
+ assertNotAttachedOriginal(spec);
+ } else if (spec.hasTag(ArtifactSpec.TAG_SHADED)) {
+ assertFalse("Single shaded artifact expected", shadedFound);
+ shadedFound = true;
+ assertReplacementUberjar(spec);
+ } else {
+ fail("Artifact should be either base or shaded");
+ }
+ }
+ }
+
+ /**
+ * Checks that for attached shaded artifact, the default output is not affected and has no tag.
+ */
+ public void testShadedAttachedDefaultOutput() throws Exception {
+ FileObject testApp = dataFO.getFileObject("artifacts/shaded-attached");
+ FileObject prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "shaded-attached");
+
+ Project p = ProjectManager.getDefault().findProject(prjCopy);
+ ProjectArtifactsQuery.ArtifactsResult ar = ProjectArtifactsQuery.findArtifacts(p,
+ ProjectArtifactsQuery.newQuery(NbMavenProject.TYPE_JAR)
+ );
+ List<ArtifactSpec> specs = ar.getArtifacts();
+ assertEquals(1, specs.size());
+ ArtifactSpec out = specs.get(0);
+ assertDefaultArtifactWithAttached(out);
+ }
+
+ /**
+ * Checks that for attached shaded artifact, the default output is not affected and has no tag.
+ */
+ public void testShadedAttachedClassifiedOutput() throws Exception {
+ FileObject testApp = dataFO.getFileObject("artifacts/shaded-attached");
+ FileObject prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "shaded-attached");
+
+ Project p = ProjectManager.getDefault().findProject(prjCopy);
+ ProjectArtifactsQuery.ArtifactsResult ar = ProjectArtifactsQuery.findArtifacts(p,
+ ProjectArtifactsQuery.newQuery(NbMavenProject.TYPE_JAR, "shaded", null)
+ );
+ List<ArtifactSpec> specs = ar.getArtifacts();
+ assertEquals(1, specs.size());
+ ArtifactSpec out = specs.get(0);
+ assertAttachedUberjar(out, "shaded");
+ }
+
+ /**
+ * Checks that for attached shaded artifact, the default output is not affected and has no tag.
+ */
+ public void testShadedAttachedClassifiedOriginalOutput() throws Exception {
+ FileObject testApp = dataFO.getFileObject("artifacts/shaded-attached");
+ FileObject prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "shaded-attached");
+
+ Project p = ProjectManager.getDefault().findProject(prjCopy);
+ ProjectArtifactsQuery.ArtifactsResult ar = ProjectArtifactsQuery.findArtifacts(p,
+ ProjectArtifactsQuery.newQuery(NbMavenProject.TYPE_JAR, "shaded", null, ArtifactSpec.TAG_BASE)
+ );
+ List<ArtifactSpec> specs = ar.getArtifacts();
+ assertEquals(1, specs.size());
+ ArtifactSpec out = specs.get(0);
+ assertAttachedOriginal(out, "shaded");
+ }
+
+ private void assertDefaultArtifactWithAttached(ArtifactSpec out) {
+ assertEquals("Output has a proper artifactId", "shaded-attached", out.getArtifactId());
+ assertEquals("Output has a proper groupId", "nbtest.grp", out.getGroupId());
+ assertNull("Output has no classifier", out.getClassifier());
+ assertFalse(out.hasTag("<shaded>"));
+ assertFalse(out.hasTag(ArtifactSpec.TAG_BASE));
+ }
+
+ private void assertAttachedUberjar(ArtifactSpec uberJar, String classifier) {
+ assertEquals("Uber-jar has a proper artifactId", "shaded-attached", uberJar.getArtifactId());
+ assertEquals("Uber-jar has a proper groupId", "nbtest.grp", uberJar.getGroupId());
+ assertEquals("Uber-jar has a classifier", classifier, uberJar.getClassifier());
+ assertTrue(uberJar.hasTag("<shaded>"));
+ assertFalse(uberJar.hasTag(ArtifactSpec.TAG_BASE));
+ }
+
+ void assertAttachedOriginal(ArtifactSpec origJar, String classifier) {
+ assertEquals("Orig-jar has an artifactId", "shaded-attached", origJar.getArtifactId());
+ assertEquals("Orig-jar has a groupId", "nbtest.grp", origJar.getGroupId());
+ assertEquals("Orig-jar has a classifier", classifier, origJar.getClassifier());
+ assertTrue(origJar.hasTag(ArtifactSpec.TAG_BASE));
+ assertFalse(origJar.hasTag(ArtifactSpec.TAG_SHADED));
+ }
+
+ /**
+ * Checks that for attached shaded artifact, the default output is not affected and has no tag.
+ */
+ public void testShadedAttachedClassifiedAllOutput() throws Exception {
+ FileObject testApp = dataFO.getFileObject("artifacts/shaded-attached");
+ FileObject prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "shaded-attached");
+
+ Project p = ProjectManager.getDefault().findProject(prjCopy);
+ ProjectArtifactsQuery.ArtifactsResult ar = ProjectArtifactsQuery.findArtifacts(p,
+ ProjectArtifactsQuery.newQuery(NbMavenProject.TYPE_JAR, ProjectArtifactsQuery.Filter.CLASSIFIER_ANY, null)
+ );
+ List<ArtifactSpec> specs = ar.getArtifacts();
+ assertEquals(3, specs.size());
+ for (ArtifactSpec out : specs) {
+ if (out.hasTag(ArtifactSpec.TAG_BASE)) {
+ assertAttachedOriginal(out, "shaded");
+ } else if (out.hasTag(ArtifactSpec.TAG_SHADED)) {
+ assertAttachedUberjar(out, "shaded");
+ } else {
+ assertDefaultArtifactWithAttached(out);
+ }
+ }
+ }
+
+ FileObject prjCopy;
+
+ private void assertAttachedClassifiedArtifact(String prjName, ArtifactSpec out, String classifier, String type) {
+ assertEquals("Output has a proper artifactId", prjName, out.getArtifactId());
+ assertEquals("Output has a proper groupId", "nbtest.grp", out.getGroupId());
+ assertEquals("Output has a classifier", classifier, out.getClassifier());
+ assertEquals("Output has a type", type, out.getType());
+ assertFalse(out.hasTag("<shaded>"));
+ assertFalse(out.hasTag(ArtifactSpec.TAG_BASE));
+
+ String suffix = classifier == null ? "" : "-" + classifier;
+
+ URI expected = FileUtil.toFile(prjCopy).toPath().resolve(Paths.get("target", prjName + "-16" + suffix + ".jar")).toUri();
+ assertEquals(expected, out.getLocation());
+ }
+
+ boolean attached;
+
+ private void assertShadedAttachedClassifiedArtifact(String prjName, ArtifactSpec out, String classifier, String type, Boolean shaded) {
+ if (Boolean.TRUE == shaded) {
+ assertTrue(out.hasTag("<shaded>"));
+ assertFalse(out.hasTag(ArtifactSpec.TAG_BASE));
+ if (attached) {
+ classifier = classifier + "-shaded";
+ }
+ } else if (Boolean.FALSE == shaded) {
+ assertFalse(out.hasTag(ArtifactSpec.TAG_SHADED));
+ assertTrue(out.hasTag(ArtifactSpec.TAG_BASE));
+ prjName = "original-" + prjName;
+ } else {
+ assertFalse(out.hasTag(ArtifactSpec.TAG_SHADED));
+ assertFalse(out.hasTag(ArtifactSpec.TAG_BASE));
+ }
+ if (attached || Boolean.FALSE != shaded) {
+ assertEquals("Output has a proper artifactId", prjName, out.getArtifactId());
+ assertEquals("Output has a proper groupId", "nbtest.grp", out.getGroupId());
+ }
+ assertEquals("Output has a classifier", classifier, out.getClassifier());
+ assertEquals("Output has a type", type, out.getType());
+
+ URI expected = FileUtil.toFile(prjCopy).toPath().resolve(Paths.get("target", prjName + "-16-" + classifier + ".jar")).toUri();
+ assertEquals(expected, out.getLocation());
+ }
+
+ public void testSourceAttachment() throws Exception {
+ FileObject testApp = dataFO.getFileObject("artifacts/sources");
+ prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "sources");
+
+ Project p = ProjectManager.getDefault().findProject(prjCopy);
+ ProjectArtifactsQuery.ArtifactsResult ar = ProjectArtifactsQuery.findArtifacts(p,
+ ProjectArtifactsQuery.newQuery(null, ArtifactSpec.CLASSIFIER_SOURCES, null)
+ );
+ List<ArtifactSpec> specs = ar.getArtifacts();
+ assertEquals(1, specs.size());
+ ArtifactSpec out = specs.get(0);
+ assertAttachedClassifiedArtifact("sources", out, "sources", "sources");
+ }
+
+ public void testTestsAttachment() throws Exception {
+ FileObject testApp = dataFO.getFileObject("artifacts/sources");
+ prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "sources");
+
+ Project p = ProjectManager.getDefault().findProject(prjCopy);
+ ProjectArtifactsQuery.ArtifactsResult ar = ProjectArtifactsQuery.findArtifacts(p,
+ ProjectArtifactsQuery.newQuery(null, ArtifactSpec.CLASSIFIER_TESTS, null)
+ );
+ List<ArtifactSpec> specs = ar.getArtifacts();
+ assertEquals(1, specs.size());
+ ArtifactSpec out = specs.get(0);
+ assertAttachedClassifiedArtifact("sources", out, "tests", "test-jar");
+ }
+
+ public void testTestsSourcesAttachment() throws Exception {
+ FileObject testApp = dataFO.getFileObject("artifacts/sources");
+ prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "sources");
+
+ Project p = ProjectManager.getDefault().findProject(prjCopy);
+ ProjectArtifactsQuery.ArtifactsResult ar = ProjectArtifactsQuery.findArtifacts(p,
+ ProjectArtifactsQuery.newQuery(null, ArtifactSpec.CLASSIFIER_TEST_SOURCES, null)
+ );
+ List<ArtifactSpec> specs = ar.getArtifacts();
+ assertEquals(1, specs.size());
+ ArtifactSpec out = specs.get(0);
+ assertAttachedClassifiedArtifact("sources", out, "test-sources", "sources");
+ }
+
+ public void testDefaultAllAttachments() throws Exception {
+ FileObject testApp = dataFO.getFileObject("artifacts/sources");
+ prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "sources");
+
+ Project p = ProjectManager.getDefault().findProject(prjCopy);
+ ProjectArtifactsQuery.ArtifactsResult ar = ProjectArtifactsQuery.findArtifacts(p,
+ ProjectArtifactsQuery.newQuery(null, ProjectArtifactsQuery.Filter.CLASSIFIER_ANY, null)
+ );
+ List<ArtifactSpec> specs = ar.getArtifacts();
+ assertEquals(4, specs.size());
+ for (ArtifactSpec out : specs) {
+ if (ArtifactSpec.CLASSIFIER_SOURCES.equals(out.getClassifier())) {
+ assertAttachedClassifiedArtifact("sources", out, "sources", "sources");
+ assertFalse(out.hasTag("test"));
+ } else if (ArtifactSpec.CLASSIFIER_TESTS.equals(out.getClassifier())) {
+ assertAttachedClassifiedArtifact("sources", out, "tests", "test-jar");
+ } else if (ArtifactSpec.CLASSIFIER_TEST_SOURCES.equals(out.getClassifier())) {
+ assertAttachedClassifiedArtifact("sources", out, "test-sources", "sources");
+ assertTrue(out.hasTag("test"));
+ } else {
+ assertAttachedClassifiedArtifact("sources", out, null, "jar");
+ }
+ }
+ }
+
+ public void testShadedSourceAttachment() throws Exception {
+ FileObject testApp = dataFO.getFileObject("artifacts/shaded-sources");
+ prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "shaded-sources");
+
+ Project p = ProjectManager.getDefault().findProject(prjCopy);
+ ProjectArtifactsQuery.ArtifactsResult ar = ProjectArtifactsQuery.findArtifacts(p,
+ ProjectArtifactsQuery.newQuery(null, ArtifactSpec.CLASSIFIER_SOURCES, null)
+ );
+ List<ArtifactSpec> specs = ar.getArtifacts();
+ assertEquals(1, specs.size());
+ ArtifactSpec out = specs.get(0);
+ assertAttachedClassifiedArtifact("shaded-sources", out, "sources", "sources");
+ assertSame(prjCopy.getFileObject("target/shaded-sources-16-sources.jar"), out.getLocalFile());
+ }
+
+ public void testShadedAllAttachments() throws Exception {
+ FileObject testApp = dataFO.getFileObject("artifacts/shaded-sources");
+ prjCopy = FileUtil.copyFile(testApp, FileUtil.toFileObject(getWorkDir()), "shaded-sources");
+
+ Project p = ProjectManager.getDefault().findProject(prjCopy);
+ ProjectArtifactsQuery.ArtifactsResult ar = ProjectArtifactsQuery.findArtifacts(p,
+ ProjectArtifactsQuery.newQuery(null, ProjectArtifactsQuery.Filter.CLASSIFIER_ANY, null)
+ );
+ List<ArtifactSpec> specs = ar.getArtifacts();
+ assertEquals(8, specs.size());
+ for (ArtifactSpec out : specs) {
+ Boolean b;
+ if (out.hasTag(ArtifactSpec.TAG_SHADED)) {
+ b = true;
+ } else if (out.hasTag(ArtifactSpec.TAG_BASE)) {
+ b = false;
+ } else {
+ fail("Only base and tagged artifacts expected");
+ return; // not reached
+ }
+ if (ArtifactSpec.CLASSIFIER_SOURCES.equals(out.getClassifier())) {
+ assertShadedAttachedClassifiedArtifact("shaded-sources", out, "sources", "sources", b);
+ assertFalse(out.hasTag("test"));
+ } else if (ArtifactSpec.CLASSIFIER_TESTS.equals(out.getClassifier())) {
+ assertShadedAttachedClassifiedArtifact("shaded-sources", out, "tests", "test-jar", b);
+ assertTrue(out.hasTag("test"));
+ } else if (ArtifactSpec.CLASSIFIER_TEST_SOURCES.equals(out.getClassifier())) {
+ assertShadedAttachedClassifiedArtifact("shaded-sources", out, "test-sources", "sources", b);
+ assertTrue(out.hasTag("test"));
+ } else {
+ if (Boolean.TRUE == b) {
+ assertReplacementUberjar(out, "shaded-sources");
+ } else if (Boolean.FALSE == b) {
+ assertNotAttachedOriginal(out);
+ }
+ }
+ }
+ }
}