Skip to content

Commit

Permalink
Backport #406 Resolve DS classpath entry and generate component xmls
Browse files Browse the repository at this point in the history
  • Loading branch information
laeubi committed Apr 21, 2022
1 parent 138591d commit a07c529
Show file tree
Hide file tree
Showing 21 changed files with 585 additions and 90 deletions.
2 changes: 2 additions & 0 deletions RELEASE_NOTES.md
Expand Up @@ -6,6 +6,8 @@ This page describes the noteworthy improvements provided by each release of Ecli
Fixes:
- [2.7.1][regression] Neither raw version nor format was specified #876
- [2.7.1] 'includePackedArtifacts' must be automatically disabled when running with an incompatible vm #885
- Resolve DS classpath entry and generate component xmls #406


## 2.7.1

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Expand Up @@ -480,7 +480,7 @@
<module>target-platform-configuration</module>
<module>tycho-maven-plugin</module>
<module>tycho-pomgenerator-plugin</module>

<module>tycho-ds-plugin</module>
<!-- surefire -->
<module>tycho-surefire</module>

Expand Down
Expand Up @@ -27,6 +27,7 @@
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.tycho.ArtifactKey;
import org.eclipse.tycho.ArtifactType;
import org.eclipse.tycho.artifacts.DependencyResolutionException;
import org.eclipse.tycho.artifacts.IllegalArtifactReferenceException;
import org.eclipse.tycho.artifacts.TargetPlatform;
import org.junit.Before;
Expand Down Expand Up @@ -159,9 +160,9 @@ public void testResolveFeature() throws Exception {

@Test
public void testResolveUnknownType() throws Exception {
IllegalArtifactReferenceException e = assertThrows(IllegalArtifactReferenceException.class,
DependencyResolutionException e = assertThrows(DependencyResolutionException.class,
() -> subject.resolveArtifact("invalid-type", "unit", ANY_VERSION));
assertTrue(e.getMessage().contains("Unknown artifact type"));
assertTrue(e.getMessage().contains("invalid-type"));
}

private FinalTargetPlatformImpl createTP() {
Expand Down
Expand Up @@ -45,6 +45,7 @@
import org.eclipse.equinox.p2.metadata.VersionRange;
import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
import org.eclipse.equinox.p2.publisher.eclipse.BundlesAction;
import org.eclipse.equinox.p2.query.IQuery;
import org.eclipse.equinox.p2.query.IQueryResult;
import org.eclipse.equinox.p2.query.QueryUtil;
import org.eclipse.equinox.spi.p2.publisher.PublisherHelper;
Expand Down Expand Up @@ -148,11 +149,9 @@ public Map<TargetEnvironment, P2ResolutionResult> resolveArtifactDependencies(Ta
for (ArtifactKey artifactKey : artifacts) {
QueryableCollection queriable = new QueryableCollection(targetPlatform.getInstallableUnits());
VersionRange range = new VersionRange(artifactKey.getVersion());
IRequirement requirement = MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID,
artifactKey.getId(), range, null, 1 /* min */, Integer.MAX_VALUE /* max */,
false /* greedy */);
IQueryResult<IInstallableUnit> result = queriable
.query(QueryUtil.createLatestQuery(QueryUtil.createMatchQuery(requirement.getMatches())), monitor);
IQuery<IInstallableUnit> query = ArtifactTypeHelper.createQueryFor(artifactKey.getType(),
artifactKey.getId(), range);
IQueryResult<IInstallableUnit> result = queriable.query(QueryUtil.createLatestQuery(query), monitor);
roots.addAll(result.toUnmodifiableSet());
}
Map<TargetEnvironment, P2ResolutionResult> results = new LinkedHashMap<>();
Expand Down
Expand Up @@ -42,11 +42,8 @@ public class ArtifactTypeHelper {
*
* @param type
* Eclipse artifact type as defined in Tycho's {@link ArtifactType}
* @throws IllegalArtifactReferenceException
* if the given artifact type is unknown
*/
public static IQuery<IInstallableUnit> createQueryFor(String type, String id, VersionRange versionRange)
throws IllegalArtifactReferenceException {
public static IQuery<IInstallableUnit> createQueryFor(String type, String id, VersionRange versionRange) {

if (ArtifactType.TYPE_ECLIPSE_PLUGIN.equals(type)) {
return QueryUtil.createMatchQuery(createBundleRequirement(id, versionRange).getMatches());
Expand All @@ -63,7 +60,10 @@ public static IQuery<IInstallableUnit> createQueryFor(String type, String id, Ve
return QueryUtil.createIUQuery(id, versionRange);

} else {
throw new IllegalArtifactReferenceException("Unknown artifact type \"" + type + "\"");

IRequirement requirement = MetadataFactory.createRequirement(type, id, versionRange, null,
1 /* min */, Integer.MAX_VALUE /* max */, false /* greedy */);
return QueryUtil.createMatchQuery(requirement.getMatches());
}
}

Expand Down
Expand Up @@ -24,6 +24,7 @@
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.Version;
import org.eclipse.equinox.p2.metadata.VersionRange;
import org.eclipse.tycho.ArtifactType;
import org.eclipse.tycho.DefaultArtifactKey;
import org.eclipse.tycho.ReactorProjectIdentities;
import org.eclipse.tycho.artifacts.DependencyResolutionException;
Expand Down Expand Up @@ -101,7 +102,10 @@ public final org.eclipse.tycho.ArtifactKey resolveArtifact(String type, String i
} else {
resolvedUnit = resolveUnit(type, id, ArtifactMatcher.parseAsOSGiVersion(version));
}
return new DefaultArtifactKey(type, id, resolvedUnit.getVersion().toString());
if (ArtifactType.TYPE_ECLIPSE_FEATURE.equals(type)) {
return new DefaultArtifactKey(type, id, resolvedUnit.getVersion().toString());
}
return new DefaultArtifactKey(type, resolvedUnit.getId(), resolvedUnit.getVersion().toString());
}

@Override
Expand Down
@@ -0,0 +1,103 @@
/*******************************************************************************
* Copyright (c) 2022 Christoph Läubrich and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Christoph Läubrich - initial API and implementation
*******************************************************************************/
package org.eclipse.tycho.artifacts.configuration;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

import org.apache.maven.model.Plugin;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.eclipse.tycho.core.DeclarativeServicesConfiguration;
import org.osgi.framework.Version;

@Component(role = DeclarativeServiceConfigurationReader.class)
public class DeclarativeServiceConfigurationReader {

public static final String DEFAULT_ADD_TO_CLASSPATH = "true";
public static final String DEFAULT_DS_VERSION = "1.3";
private static final String PROPERTY_CLASSPATH = "classpath";
private static final String PROPERTY_DS_VERSION = "dsVersion";
private static final String PROPERTY_ENABLED = "enabled";

private static final String PDE_DS_ANNOTATIONS_PREFS = ".settings/org.eclipse.pde.ds.annotations.prefs";

@Requirement
private Logger logger;

public DeclarativeServicesConfiguration getConfiguration(MavenProject mavenProject) throws IOException {
Properties settings = getProjectSettings(mavenProject.getBasedir(), getMojoSettings(mavenProject, logger),
mavenProject, logger);
if (Boolean.parseBoolean(settings.getProperty(PROPERTY_ENABLED))) {
return new DeclarativeServicesConfiguration() {

@Override
public boolean isAddToClasspath() {
return Boolean.parseBoolean(settings.getProperty(PROPERTY_CLASSPATH, DEFAULT_ADD_TO_CLASSPATH));
}

@Override
public Version getSpecificationVersion() {
String property = settings.getProperty(PROPERTY_DS_VERSION, DEFAULT_DS_VERSION);
if (property.startsWith("V")) {
property = property.substring(1).replace('_', '.');
}
return Version.parseVersion(property);
}
};
}
return null;
}

private static Properties getProjectSettings(File basedir, Properties mojoProperties, MavenProject mavenProject,
Logger logger) throws FileNotFoundException, IOException {
Properties properties = new Properties(mojoProperties);
File prefs = new File(basedir, PDE_DS_ANNOTATIONS_PREFS);
if (prefs.exists()) {
try (FileInputStream stream = new FileInputStream(prefs)) {
properties.load(stream);
logger.debug("declarative-services project configuration for " + mavenProject.toString() + ":"
+ System.lineSeparator() + properties);
}
}
return properties;
}

private static Properties getMojoSettings(MavenProject project, Logger logger) {
Properties properties = new Properties();
Plugin plugin = project.getPlugin("org.eclipse.tycho:tycho-ds-plugin");
if (plugin != null) {
Xpp3Dom configuration = (Xpp3Dom) plugin.getConfiguration();
if (configuration != null) {
if (logger.isDebugEnabled()) {
logger.debug("declarative-services mojo configuration for " + project.toString() + ":"
+ System.lineSeparator() + configuration.toString());
}
setProperty(properties, PROPERTY_CLASSPATH, configuration.getAttribute(PROPERTY_CLASSPATH));
setProperty(properties, PROPERTY_DS_VERSION, configuration.getAttribute(PROPERTY_DS_VERSION));
setProperty(properties, PROPERTY_ENABLED, configuration.getAttribute(PROPERTY_ENABLED));
}
}
return properties;
}

private static void setProperty(Properties properties, String key, String attribute) {
if (attribute != null && !attribute.isEmpty()) {
properties.setProperty(key, attribute);
}
}
}
@@ -0,0 +1,28 @@
/*******************************************************************************
* Copyright (c) 2022 Christoph Läubrich and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Christoph Läubrich - initial API and implementation
*******************************************************************************/
package org.eclipse.tycho.core;

import org.osgi.framework.Version;

public interface DeclarativeServicesConfiguration {

/**
* Controls if the DS components annotations are made available on the compile-classpath, this
* means no explicit import is required.
*/
boolean isAddToClasspath();

/**
* Controls the declarative services specification version to use.
*/
Version getSpecificationVersion();

}
Expand Up @@ -47,16 +47,21 @@
import org.eclipse.tycho.ArtifactDescriptor;
import org.eclipse.tycho.ArtifactKey;
import org.eclipse.tycho.ArtifactType;
import org.eclipse.tycho.DefaultArtifactKey;
import org.eclipse.tycho.PackagingType;
import org.eclipse.tycho.ReactorProject;
import org.eclipse.tycho.TychoConstants;
import org.eclipse.tycho.artifacts.DependencyArtifacts;
import org.eclipse.tycho.artifacts.DependencyResolutionException;
import org.eclipse.tycho.artifacts.IllegalArtifactReferenceException;
import org.eclipse.tycho.artifacts.TargetPlatform;
import org.eclipse.tycho.artifacts.configuration.DeclarativeServiceConfigurationReader;
import org.eclipse.tycho.classpath.ClasspathEntry;
import org.eclipse.tycho.classpath.ClasspathEntry.AccessRule;
import org.eclipse.tycho.core.ArtifactDependencyVisitor;
import org.eclipse.tycho.core.ArtifactDependencyWalker;
import org.eclipse.tycho.core.BundleProject;
import org.eclipse.tycho.core.DeclarativeServicesConfiguration;
import org.eclipse.tycho.core.PluginDescription;
import org.eclipse.tycho.core.TargetPlatformConfiguration;
import org.eclipse.tycho.core.TychoProject;
Expand Down Expand Up @@ -118,6 +123,9 @@ public class OsgiBundleProject extends AbstractTychoProject implements BundlePro
@Requirement
private EquinoxServiceFactory equinox;

@Requirement
private DeclarativeServiceConfigurationReader dsConfigReader;

@Override
public ArtifactDependencyWalker getDependencyWalker(ReactorProject project, TargetEnvironment environment) {
return getDependencyWalker(project);
Expand Down Expand Up @@ -508,6 +516,27 @@ private void addExtraClasspathEntries(List<ClasspathEntry> classpath, ReactorPro
.add(new DefaultClasspathEntry(project, projectKey, Collections.singletonList(location), null));
}
}
try {
DeclarativeServicesConfiguration configuration = dsConfigReader.getConfiguration(getMavenProject(project));
if (configuration != null && configuration.isAddToClasspath()) {
TargetPlatform tp = TychoProjectUtils.getTargetPlatform(project);
org.osgi.framework.Version specificationVersion = configuration.getSpecificationVersion();
ArtifactKey dsJar = tp.resolveArtifact("java.package",
"org.osgi.service.component.annotations",
"[" + specificationVersion + "," + (specificationVersion.getMajor() + 1) + ".0.0)");
File location = tp.getArtifactLocation(
new DefaultArtifactKey(ArtifactType.TYPE_ECLIPSE_PLUGIN, dsJar.getId(), dsJar.getVersion()));
logger.debug("Resolved declarative service specification " + specificationVersion + " to "
+ dsJar.getId() + " " + dsJar.getVersion() + " " + location);
DefaultAccessRule rule = new DefaultAccessRule("org/osgi/service/component/annotations/*", false);
classpath.add(new DefaultClasspathEntry(project, getArtifactKey(project),
Collections.singletonList(location), List.of(rule)));
}
} catch (IOException e) {
logger.warn("Can't read Declarative Services Configuration: " + e.getMessage(), e);
} catch (IllegalArtifactReferenceException | DependencyResolutionException e) {
logger.warn("Can't find declarative service specification in target platform: " + e.getMessage(), e);
}
}

protected DefaultClasspathEntry addBundleToClasspath(ArtifactDescriptor matchingBundle, String path) {
Expand Down
42 changes: 42 additions & 0 deletions tycho-ds-plugin/pom.xml
@@ -0,0 +1,42 @@
<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>
<parent>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho</artifactId>
<version>2.7.2-SNAPSHOT</version>
</parent>
<artifactId>tycho-ds-plugin</artifactId>
<packaging>maven-plugin</packaging>

<name>Tycho OSGi Declarative Services Plugin</name>
<description>A plugin for handling OSGi Declarative Services</description>

<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>biz.aQute.bnd</groupId>
<artifactId>biz.aQute.bndlib</artifactId>
<version>6.2.0</version>
</dependency>
</dependencies>
</project>

0 comments on commit a07c529

Please sign in to comment.