diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index cc1b9f6725..92cbf0f13c 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -6,6 +6,7 @@ This page describes the noteworthy improvements provided by each release of Ecli
### backports:
+- support for embedded target locations
- using javac as the compiler for Tycho
- new `mirror-target-platform` mojo
- new director mojo
diff --git a/target-platform-configuration/src/main/java/org/eclipse/tycho/target/TargetParameterObject.java b/target-platform-configuration/src/main/java/org/eclipse/tycho/target/TargetParameterObject.java
index 1bb03d319f..5e48ab4615 100644
--- a/target-platform-configuration/src/main/java/org/eclipse/tycho/target/TargetParameterObject.java
+++ b/target-platform-configuration/src/main/java/org/eclipse/tycho/target/TargetParameterObject.java
@@ -12,6 +12,7 @@
import java.io.File;
import java.net.URI;
+import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.eclipse.tycho.p2.repository.GAV;
/**
@@ -23,4 +24,5 @@ public class TargetParameterObject {
public GAV target;
public File file;
public URI uri;
+ public PlexusConfiguration location;
}
diff --git a/target-platform-configuration/src/main/java/org/eclipse/tycho/target/TargetPlatformConfigurationMojo.java b/target-platform-configuration/src/main/java/org/eclipse/tycho/target/TargetPlatformConfigurationMojo.java
index 5b8a39a0f7..23cd5b3d51 100644
--- a/target-platform-configuration/src/main/java/org/eclipse/tycho/target/TargetPlatformConfigurationMojo.java
+++ b/target-platform-configuration/src/main/java/org/eclipse/tycho/target/TargetPlatformConfigurationMojo.java
@@ -89,6 +89,7 @@ public class TargetPlatformConfigurationMojo extends AbstractMojo {
*
<file>
to define a file local to the build
* <uri>
to define a (remote) URI that specifies a target, currently only
* URIs that can be converted to URLs are supported (e.g. file:/.... http://..., )
+ * {@code } to define target locations inline
*
*/
@Parameter(name = DefaultTargetPlatformConfigurationReader.TARGET)
diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/TargetPlatformConfiguration.java b/tycho-core/src/main/java/org/eclipse/tycho/core/TargetPlatformConfiguration.java
index e8393a80a0..2ba176aa5d 100644
--- a/tycho-core/src/main/java/org/eclipse/tycho/core/TargetPlatformConfiguration.java
+++ b/tycho-core/src/main/java/org/eclipse/tycho/core/TargetPlatformConfiguration.java
@@ -17,7 +17,9 @@
import java.io.File;
import java.net.URI;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.Base64;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -28,6 +30,7 @@
import java.util.Set;
import java.util.function.Supplier;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.eclipse.equinox.p2.metadata.IRequirement;
import org.eclipse.tycho.ArtifactKey;
import org.eclipse.tycho.OptionalResolutionAction;
@@ -121,6 +124,8 @@ public enum InjectP2MavenMetadataHandling {
private ReferencedRepositoryMode referencedRepositoryMode = ReferencedRepositoryMode.ignore;
+ private List xmlFragments = new ArrayList<>();
+
/**
* Returns the list of configured target environments, or the running environment if no
* environments have been specified explicitly.
@@ -141,6 +146,18 @@ public synchronized List getTargets() {
targets.add(supplier.get().toURI());
iterator.remove();
}
+ if (!xmlFragments.isEmpty()) {
+ Xpp3Dom target = new Xpp3Dom("target");
+ Xpp3Dom locations = new Xpp3Dom(TargetDefinitionFile.ELEMENT_LOCATIONS);
+ target.addChild(locations);
+ for (Xpp3Dom location : xmlFragments) {
+ locations.addChild(new Xpp3Dom(location));
+ }
+ String collect = target.toString();
+ targets.add(URI.create("data:" + TargetDefinitionFile.APPLICATION_TARGET + ";base64,"
+ + Base64.getEncoder().encodeToString(collect.getBytes(StandardCharsets.UTF_8))));
+ xmlFragments.clear();
+ }
return targets.stream().map(TargetDefinitionFile::read).toList();
}
@@ -319,4 +336,8 @@ public void setReferencedRepositoryMode(ReferencedRepositoryMode referencedRepos
this.referencedRepositoryMode = referencedRepositoryMode;
}
+ public void addTargetLocation(Xpp3Dom locationDom) {
+ xmlFragments.add(locationDom);
+ }
+
}
diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/DefaultTargetPlatformConfigurationReader.java b/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/DefaultTargetPlatformConfigurationReader.java
index 169ea2941a..c9cd9d6863 100644
--- a/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/DefaultTargetPlatformConfigurationReader.java
+++ b/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/DefaultTargetPlatformConfigurationReader.java
@@ -331,10 +331,10 @@ private void setBREEHeaderSelectionPolicy(TargetPlatformConfiguration result, Xp
/**
* Take the constraints of the configured execution environment into account when resolving
- * dependencies or target definitions. These constraints include the list of system packages and the
- * Bundle-RequiredExecutionEnvironment header. When set to true
, the
- * dependency resolution verifies that the bundle and all required bundles can be used in an OSGi
- * container with the configured execution environment.
+ * dependencies or target definitions. These constraints include the list of system packages and
+ * the Bundle-RequiredExecutionEnvironment header. When set to true
, the
+ * dependency resolution verifies that the bundle and all required bundles can be used in an
+ * OSGi container with the configured execution environment.
*/
private void setResolveWithEEContraints(TargetPlatformConfiguration result, Xpp3Dom resolverDom) {
String value = getStringValue(resolverDom.getChild(RESOLVE_WITH_EXECUTION_ENVIRONMENT_CONSTRAINTS));
@@ -462,6 +462,13 @@ private void setTarget(TargetPlatformConfiguration result, MavenSession session,
}
}
}
+ Xpp3Dom[] locationsArray = targetDom.getChildren("location");
+ if (locationsArray != null && locationsArray.length > 0) {
+ for (Xpp3Dom locationDom : locationsArray) {
+ result.addTargetLocation(locationDom);
+ }
+ }
+
}
protected void addTargetArtifact(TargetPlatformConfiguration result, MavenSession session, MavenProject project,
@@ -592,9 +599,9 @@ private static String getStringValue(Xpp3Dom element) {
*
* @param project
* @param targetFile
- * the target file to check
+ * the target file to check
* @param otherTargetFiles
- * other target files to take into account
+ * other target files to take into account
* @return true
if the target file is the primary artifact, false
* otherwise
*/
diff --git a/tycho-targetplatform/src/main/java/org/eclipse/tycho/targetplatform/TargetDefinitionFile.java b/tycho-targetplatform/src/main/java/org/eclipse/tycho/targetplatform/TargetDefinitionFile.java
index 0cda363213..53549f0cd5 100644
--- a/tycho-targetplatform/src/main/java/org/eclipse/tycho/targetplatform/TargetDefinitionFile.java
+++ b/tycho-targetplatform/src/main/java/org/eclipse/tycho/targetplatform/TargetDefinitionFile.java
@@ -21,14 +21,17 @@
package org.eclipse.tycho.targetplatform;
import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
+import java.net.MalformedURLException;
import java.net.URI;
import java.text.MessageFormat;
import java.util.ArrayList;
+import java.util.Base64;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
@@ -65,7 +68,8 @@
public final class TargetDefinitionFile implements TargetDefinition {
- private static final Map FILE_CACHE = new ConcurrentHashMap<>();
+ public static final String ELEMENT_LOCATIONS = "locations";
+ private static final Map FILE_CACHE = new ConcurrentHashMap<>();
//just for information purpose
private final String origin;
@@ -75,6 +79,7 @@ public final class TargetDefinitionFile implements TargetDefinition {
private String targetEE;
public static final String FILE_EXTENSION = ".target";
+ public static final String APPLICATION_TARGET = "application/target";
private abstract static class AbstractPathLocation implements TargetDefinition.PathLocation {
private String path;
@@ -554,8 +559,8 @@ public static TargetDefinitionFile read(URI uri) {
try {
return FILE_CACHE.computeIfAbsent(uri.normalize(), key -> {
try {
- try (InputStream input = uri.toURL().openStream()) {
- return parse(parseDocument(input), uri.toASCIIString());
+ try (InputStream input = openTargetStream(uri)) {
+ return parse(parseDocument(input), getOrigin(uri));
} catch (ParserConfigurationException e) {
throw new TargetDefinitionSyntaxException("No valid XML parser: " + e.getMessage(), e);
} catch (SAXException e) {
@@ -573,6 +578,31 @@ public static TargetDefinitionFile read(URI uri) {
}
}
+ private static String getOrigin(URI uri) {
+ if (isDataUrl(uri)) {
+ return "";
+ }
+ return uri.toASCIIString();
+ }
+
+ private static InputStream openTargetStream(URI uri) throws IOException, MalformedURLException {
+ if (isDataUrl(uri)) {
+ String rawPath = uri.toASCIIString();
+ int indexOf = rawPath.indexOf(',');
+ if (indexOf > -1) {
+ String data = rawPath.substring(indexOf + 1);
+ return new ByteArrayInputStream(Base64.getDecoder().decode(data));
+ } else {
+ throw new MalformedURLException("invalid data url!");
+ }
+ }
+ return uri.toURL().openStream();
+ }
+
+ private static boolean isDataUrl(URI uri) {
+ return "data".equals(uri.getScheme());
+ }
+
public static TargetDefinitionFile parse(Document document, String origin) {
return new TargetDefinitionFile(document, origin);
}
@@ -618,7 +648,7 @@ public static boolean isTargetFile(File file) {
private static List extends TargetDefinition.Location> parseLocations(Element dom) {
ArrayList locations = new ArrayList<>();
- Element locationsDom = getChild(dom, "locations");
+ Element locationsDom = getChild(dom, ELEMENT_LOCATIONS);
if (locationsDom != null) {
for (Element locationDom : getChildren(locationsDom, "location")) {
String type = locationDom.getAttribute("type");