diff --git a/m2e-maven-runtime/org.eclipse.m2e.archetype.common/pom.xml b/m2e-maven-runtime/org.eclipse.m2e.archetype.common/pom.xml
index 61537457a..c21f8a642 100644
--- a/m2e-maven-runtime/org.eclipse.m2e.archetype.common/pom.xml
+++ b/m2e-maven-runtime/org.eclipse.m2e.archetype.common/pom.xml
@@ -19,7 +19,7 @@
org.eclipse.m2e.archetype.common
- 1.18.1-SNAPSHOT
+ 1.19.0-SNAPSHOT
eclipse-plugin
M2E Maven Archetype Common
@@ -99,7 +99,7 @@
org.apache.maven.archetype.*;provider=m2e;mandatory:=provider;x-internal:=true,
org.codehaus.plexus.velocity;provider=m2e;mandatory:=provider;x-internal:=true,
- org.eclipse.m2e.maven.runtime;bundle-version="[1.18.0,1.19.0)"
+ org.eclipse.m2e.maven.runtime;bundle-version="[1.18.0,2)"
diff --git a/m2e-maven-runtime/org.eclipse.m2e.maven.indexer/pom.xml b/m2e-maven-runtime/org.eclipse.m2e.maven.indexer/pom.xml
index 91adf3665..eeca34f42 100644
--- a/m2e-maven-runtime/org.eclipse.m2e.maven.indexer/pom.xml
+++ b/m2e-maven-runtime/org.eclipse.m2e.maven.indexer/pom.xml
@@ -19,7 +19,7 @@
org.eclipse.m2e.maven.indexer
- 1.18.1-SNAPSHOT
+ 1.19.0-SNAPSHOT
eclipse-plugin
M2E Maven/Nexus Indexer
@@ -114,8 +114,8 @@
javax.inject;version="1.0.0"
- org.eclipse.m2e.maven.runtime;bundle-version="[1.18.0,1.19.0)",
- org.eclipse.m2e.archetype.common;bundle-version="[1.18.0,1.19.0)",
+ org.eclipse.m2e.maven.runtime;bundle-version="[1.18.0,2)",
+ org.eclipse.m2e.archetype.common;bundle-version="[1.18.0,2)",
com.google.guava
diff --git a/m2e-maven-runtime/org.eclipse.m2e.maven.runtime.slf4j.simple/pom.xml b/m2e-maven-runtime/org.eclipse.m2e.maven.runtime.slf4j.simple/pom.xml
index c0e325e05..485637e2c 100644
--- a/m2e-maven-runtime/org.eclipse.m2e.maven.runtime.slf4j.simple/pom.xml
+++ b/m2e-maven-runtime/org.eclipse.m2e.maven.runtime.slf4j.simple/pom.xml
@@ -19,7 +19,7 @@
org.eclipse.m2e.maven.runtime.slf4j.simple
- 1.18.1-SNAPSHOT
+ 1.19.0-SNAPSHOT
eclipse-plugin
M2E SLF4J-Simple Binding for Embedded Maven Runtime
diff --git a/m2e-maven-runtime/org.eclipse.m2e.maven.runtime/pom.xml b/m2e-maven-runtime/org.eclipse.m2e.maven.runtime/pom.xml
index 94c3ab788..fb90bee4c 100644
--- a/m2e-maven-runtime/org.eclipse.m2e.maven.runtime/pom.xml
+++ b/m2e-maven-runtime/org.eclipse.m2e.maven.runtime/pom.xml
@@ -19,7 +19,7 @@
org.eclipse.m2e.maven.runtime
- 1.18.2-SNAPSHOT
+ 1.19.0-SNAPSHOT
eclipse-plugin
M2E Embedded Maven Runtime (includes Incubating components)
@@ -155,7 +155,7 @@
javax.inject;version="1.0.0"
- org.eclipse.m2e.maven.runtime.slf4j.simple;bundle-version="[1.18.0,1.19.0)",
+ org.eclipse.m2e.maven.runtime.slf4j.simple;bundle-version="[1.18.0,2)",
com.google.guava
TODO we should generate a
- // feature from them!
+ if (isPomType(artifact)) {
+ MavenTargetFeature feature = new MavenTargetFeature(new MavenPomFeatureModel(artifact, targetBundles));
+ targetBundles.features.add(feature);
return;
}
BNDInstructions bndInstructions = instructionsMap.get(getKey(artifact));
@@ -239,7 +310,7 @@ private void addBundleForArtifact(Artifact artifact, CacheManager cacheManager,
public MavenTargetLocation update(IProgressMonitor monitor) throws CoreException {
- List latest = new ArrayList<>();
+ List latest = new ArrayList();
int updated = 0;
for (MavenTargetDependency dependency : roots) {
Artifact artifact = new DefaultArtifact(
@@ -284,7 +355,7 @@ public VersionRangeResult call(IMavenExecutionContext context, IProgressMonitor
}
return new MavenTargetLocation(latest, extraRepositories, metadataMode, dependencyScope, includeSource,
- instructionsMap.values(), excludedArtifacts);
+ instructionsMap.values(), excludedArtifacts, featureTemplate);
}
@@ -294,7 +365,11 @@ public List getRoots() {
public MavenTargetLocation withInstructions(Collection instructions) {
return new MavenTargetLocation(roots, extraRepositories, metadataMode, dependencyScope, includeSource,
- instructions, excludedArtifacts);
+ instructions, excludedArtifacts, featureTemplate);
+ }
+
+ public IFeature getFeatureTemplate() {
+ return featureTemplate;
}
public BNDInstructions getInstructions(Artifact artifact) {
@@ -327,15 +402,18 @@ public int getDependencyCount() {
}
List getDependencyNodes(MavenTargetDependency dependency) {
- return dependencyNodes.get(dependency);
+ TargetBundles bundles = targetBundles;
+ if (bundles == null) {
+ return Collections.emptyList();
+ }
+ return bundles.dependencyNodes.get(dependency);
}
@Override
protected TargetFeature[] resolveFeatures(ITargetDefinition definition, IProgressMonitor monitor)
throws CoreException {
- // XXX it would be possible to deploy features as maven artifacts, are there any
- // examples?
- return new TargetFeature[] {};
+ return resolveArtifacts(definition, monitor).stream().flatMap(tb -> tb.features.stream())
+ .toArray(TargetFeature[]::new);
}
@Override
@@ -350,7 +428,7 @@ public String getLocation(boolean resolve) throws CoreException {
@Override
public int hashCode() {
- return Objects.hash(roots, dependencyNodes, dependencyScope, failedArtifacts, metadataMode);
+ return Objects.hash(roots, dependencyScope, failedArtifacts, metadataMode);
}
@Override
@@ -365,8 +443,7 @@ public boolean equals(Object obj) {
return false;
}
MavenTargetLocation other = (MavenTargetLocation) obj;
- return Objects.equals(roots, other.roots) && Objects.equals(dependencyNodes, other.dependencyNodes)
- && Objects.equals(dependencyScope, other.dependencyScope)
+ return Objects.equals(roots, other.roots) && Objects.equals(dependencyScope, other.dependencyScope)
&& Objects.equals(failedArtifacts, other.failedArtifacts);
}
@@ -383,6 +460,12 @@ public String serialize() {
attribute(xml, ATTRIBUTE_DEPENDENCY_SCOPE, dependencyScope);
attribute(xml, ATTRIBUTE_INCLUDE_SOURCE, includeSource ? "true" : "");
xml.append(">");
+ if (featureTemplate != null) {
+ try (PrintWriter writer = new PrintWriter(new StringBuilderWriter(xml))) {
+ featureTemplate.write("", writer);
+ writer.flush();
+ }
+ }
if (!roots.isEmpty()) {
xml.append("<" + ELEMENT_DEPENDENCIES + ">");
roots.stream().sorted(Comparator.comparing(MavenTargetDependency::getKey)).forEach(dependency -> {
@@ -416,9 +499,12 @@ public String serialize() {
xml.append(instructions);
xml.append("\r\n]]>" + ELEMENT_INSTRUCTIONS + ">");
});
- excludedArtifacts.stream().sorted().forEach(ignored -> element(xml, ELEMENT_EXCLUDED, ignored));
+ excludedArtifacts.stream().sorted().forEach(ignored -> {
+ element(xml, ELEMENT_EXCLUDED, ignored);
+ });
xml.append("");
- return xml.toString();
+ String string = xml.toString();
+ return string;
}
private static void element(StringBuilder xml, String name, String value) {
@@ -452,7 +538,6 @@ public MissingMetadataMode getMetadataMode() {
}
public void refresh() {
- dependencyNodes.clear();
targetBundles = null;
clearResolutionStatus();
}
@@ -491,22 +576,15 @@ public void setExcluded(Artifact artifact, boolean disabled) {
public MavenTargetBundle getMavenTargetBundle(Artifact artifact) {
TargetBundles bundles = targetBundles;
if (bundles != null) {
- TargetBundle targetBundle = bundles.bundles.get(artifact);
- if (targetBundle instanceof MavenTargetBundle) {
- return (MavenTargetBundle) targetBundle;
- }
+ return bundles.getTargetBundle(artifact).orElse(null);
}
return null;
}
public MavenTargetBundle getMavenTargetBundle(MavenTargetDependency dependency) {
- List list = dependencyNodes.get(dependency);
- if (list != null) {
- for (DependencyNode node : list) {
- if (node.getData().get(DEPENDENCYNODE_ROOT) == dependency) {
- return getMavenTargetBundle(node.getArtifact());
- }
- }
+ TargetBundles bundles = targetBundles;
+ if (bundles != null) {
+ return bundles.getTargetBundle(dependency).orElse(null);
}
return null;
}
diff --git a/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/MavenTargetLocationFactory.java b/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/MavenTargetLocationFactory.java
index 2000215ab..f5d0f3c69 100644
--- a/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/MavenTargetLocationFactory.java
+++ b/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/MavenTargetLocationFactory.java
@@ -16,6 +16,7 @@
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
+import java.util.stream.IntStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -25,6 +26,7 @@
import org.eclipse.core.runtime.Status;
import org.eclipse.pde.core.target.ITargetLocation;
import org.eclipse.pde.core.target.ITargetLocationFactory;
+import org.eclipse.pde.internal.core.ifeature.IFeature;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
@@ -97,9 +99,13 @@ public ITargetLocation getTargetLocation(String type, String serializedXML) thro
excludes.add(((Element) item).getTextContent());
}
}
+ NodeList featuresNodeList = location.getElementsByTagName(MavenTargetLocation.ELEMENT_FEATURE);
+ IFeature templateFeature = IntStream.range(0, featuresNodeList.getLength())
+ .mapToObj(index -> featuresNodeList.item(index)).map(DomXmlFeature::new).findFirst().orElse(null);
+
return new MavenTargetLocation(dependencies, repositories, mode, dependencyScope,
Boolean.parseBoolean(location.getAttribute(MavenTargetLocation.ATTRIBUTE_INCLUDE_SOURCE)),
- instructions, excludes);
+ instructions, excludes, templateFeature);
} catch (Exception e) {
throw new CoreException(new Status(IStatus.ERROR, MavenTargetLocationFactory.class.getPackage().getName(),
e.getMessage(), e));
diff --git a/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/TargetBundles.java b/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/TargetBundles.java
index cb80eb1cb..f1aa0664e 100644
--- a/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/TargetBundles.java
+++ b/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/TargetBundles.java
@@ -12,13 +12,21 @@
*******************************************************************************/
package org.eclipse.m2e.pde;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
+import org.apache.maven.model.Model;
import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.graph.DependencyNode;
import org.eclipse.pde.core.target.TargetBundle;
+import org.eclipse.pde.core.target.TargetFeature;
+
+import aQute.bnd.version.Version;
/**
* represents a resolved set of {@link Artifact} -> {@link TargetBundle}
@@ -26,4 +34,56 @@
class TargetBundles {
final Map bundles = new HashMap<>();
final Set ignoredArtifacts = new HashSet<>();
+ final List features = new ArrayList<>();
+ final Map> dependencyNodes = new HashMap<>();
+
+ Optional getDependencyNode(Artifact artifact) {
+ return dependencyNodes.values().stream().flatMap(l -> l.stream())
+ .filter(node -> artifact.equals(node.getArtifact())).findAny();
+ }
+
+ Optional getTargetBundle(Artifact artifact) {
+ TargetBundle targetBundle = bundles.get(artifact);
+ if (targetBundle instanceof MavenTargetBundle) {
+ return Optional.of((MavenTargetBundle) targetBundle);
+ }
+ return Optional.empty();
+ }
+
+ Optional getTargetBundle(MavenTargetDependency dependency) {
+ List list = dependencyNodes.get(dependency);
+ if (list != null) {
+ Optional artifact = list.stream()
+ .filter(node -> node.getData().get(MavenTargetLocation.DEPENDENCYNODE_ROOT) == dependency)
+ .findFirst().map(DependencyNode::getArtifact);
+ return artifact.flatMap(this::getTargetBundle);
+ }
+ return Optional.empty();
+ }
+
+ public static Version createOSGiVersion(Artifact artifact) {
+ String version = artifact.getVersion();
+ return createOSGiVersion(version);
+ }
+
+ public static Version createOSGiVersion(Model model) {
+ return createOSGiVersion(model.getVersion());
+ }
+
+ public static Version createOSGiVersion(String version) {
+ if (version == null || version.isEmpty()) {
+ return new Version(0, 0, 1);
+ }
+ try {
+ int index = version.indexOf('-');
+ if (index > -1) {
+ StringBuilder sb = new StringBuilder(version);
+ sb.setCharAt(index, '.');
+ return Version.parseVersion(sb.toString());
+ }
+ return Version.parseVersion(version);
+ } catch (IllegalArgumentException e) {
+ return new Version(0, 0, 1, version);
+ }
+ }
}
diff --git a/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/TemplateFeatureModel.java b/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/TemplateFeatureModel.java
new file mode 100644
index 000000000..e43f345a0
--- /dev/null
+++ b/org.eclipse.m2e.pde/src/org/eclipse/m2e/pde/TemplateFeatureModel.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2021 Christoph Läubrich
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-v20.html
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Christoph Läubrich - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.m2e.pde;
+
+import java.io.ByteArrayInputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.charset.StandardCharsets;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.pde.internal.core.NLResourceHelper;
+import org.eclipse.pde.internal.core.feature.AbstractFeatureModel;
+import org.eclipse.pde.internal.core.feature.Feature;
+import org.eclipse.pde.internal.core.ifeature.IFeature;
+
+/**
+ * creates a new model by copy the a given {@link IFeature} as its template
+ */
+@SuppressWarnings("restriction")
+public final class TemplateFeatureModel extends AbstractFeatureModel {
+
+ private static final long serialVersionUID = 1L;
+ private String xml;
+ private boolean editable = true;
+
+ public TemplateFeatureModel(IFeature template) {
+ if (template != null) {
+ StringWriter stringWriter = new StringWriter();
+ try (PrintWriter writer = new PrintWriter(stringWriter)) {
+ template.write("", writer);
+ writer.flush();
+ }
+ this.xml = stringWriter.toString();
+ }
+ }
+
+ @Override
+ public synchronized void load() throws CoreException {
+ if (xml != null && isEditable()) {
+ load(new ByteArrayInputStream(xml.getBytes(StandardCharsets.UTF_8)), false);
+ updateTimeStampWith(System.currentTimeMillis());
+ setLoaded(true);
+ xml = null;
+ }
+ }
+
+ @Override
+ protected NLResourceHelper createNLResourceHelper() {
+ return null;
+ }
+
+ @Override
+ public boolean isEditable() {
+ return editable;
+ }
+
+ public void makeReadOnly() {
+ this.editable = false;
+ }
+
+ @Override
+ public IFeature getFeature() {
+ if (feature == null) {
+ feature = new TemplateFeature(this);
+ }
+ return feature;
+ }
+
+ private static final class TemplateFeature extends Feature {
+
+ public TemplateFeature(TemplateFeatureModel templateFeatureModel) {
+ setModel(templateFeatureModel);
+ }
+
+ @Override
+ public boolean isValid() {
+ return hasRequiredAttributes();
+ }
+ }
+}
diff --git a/target-platform/target-platform.target b/target-platform/target-platform.target
index e27bb104d..d41a2b81f 100644
--- a/target-platform/target-platform.target
+++ b/target-platform/target-platform.target
@@ -26,7 +26,7 @@
-
+