Skip to content

Commit

Permalink
Support site/product in TychoGraphBuilder requests
Browse files Browse the repository at this point in the history
Currently only bundle and feature projects are supported for
-pl/-am/-amd options when using the TychoGraphBuilder, this should be
enhanced to also support sites and products
  • Loading branch information
laeubi committed Jun 21, 2022
1 parent 27bac24 commit e908004
Show file tree
Hide file tree
Showing 17 changed files with 791 additions and 88 deletions.
15 changes: 15 additions & 0 deletions p2-maven-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@
<artifactId>org.eclipse.equinox.p2.publisher.eclipse</artifactId>
<version>1.4.100</version>
</dependency>
<dependency>
<groupId>org.eclipse.platform</groupId>
<artifactId>org.eclipse.equinox.frameworkadmin</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-model</artifactId>
Expand All @@ -92,6 +97,16 @@
<artifactId>org.eclipse.equinox.p2.metadata.repository</artifactId>
<version>1.4.100</version>
</dependency>
<dependency>
<groupId>org.eclipse.platform</groupId>
<artifactId>org.eclipse.equinox.p2.updatesite</artifactId>
<version>1.2.300</version>
</dependency>
<dependency>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-embedder-api</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/*******************************************************************************
* 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.p2maven;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.annotations.Component;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.equinox.internal.p2.publisher.eclipse.FeatureParser;
import org.eclipse.equinox.internal.p2.publisher.eclipse.IProductDescriptor;
import org.eclipse.equinox.internal.p2.updatesite.CategoryParser;
import org.eclipse.equinox.internal.p2.updatesite.SiteModel;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.publisher.IPublisherAction;
import org.eclipse.equinox.p2.publisher.IPublisherInfo;
import org.eclipse.equinox.p2.publisher.PublisherInfo;
import org.eclipse.equinox.p2.publisher.PublisherResult;
import org.eclipse.equinox.p2.publisher.eclipse.BundlesAction;
import org.eclipse.equinox.p2.publisher.eclipse.Feature;
import org.eclipse.equinox.p2.publisher.eclipse.FeaturesAction;
import org.eclipse.equinox.p2.query.QueryUtil;
import org.eclipse.tycho.PackagingType;
import org.eclipse.tycho.p2maven.actions.CategoryDependenciesAction;
import org.eclipse.tycho.p2maven.actions.ProductDependenciesAction;
import org.eclipse.tycho.p2maven.actions.ProductFile2;
import org.xml.sax.SAXException;

/**
* Component used to generate {@link IInstallableUnit}s from other artifacts
*
*/
@Component(role = InstallableUnitGenerator.class)
public class InstallableUnitGenerator {

private static final String KEY_UNITS = "InstallableUnitGenerator.units";

/**
* Computes the {@link IInstallableUnit}s for the given project, the computation
* is cached unless forceUpdate is <code>true</code> meaning data is always
* regenerated from scratch.
*
* @param project the project to examine
* @param forceUpdate if cached data is fine
* @return a (possibly empty) collection of {@link IInstallableUnit}s for the
* given {@link MavenProject}
* @throws CoreException if anything goes wrong
*/
@SuppressWarnings("unchecked")
public Collection<IInstallableUnit> getInstallableUnits(MavenProject project, boolean forceUpdate)
throws CoreException {
synchronized (project) {
if (!forceUpdate) {
Object contextValue = project.getContextValue(KEY_UNITS);
if (contextValue instanceof Collection<?>) {
return (Collection<IInstallableUnit>) contextValue;
}
}
List<IPublisherAction> actions = new ArrayList<>();

File basedir = project.getBasedir();
if (basedir == null || !basedir.isDirectory()) {
return Collections.emptyList();
}
switch (project.getPackaging()) {
case PackagingType.TYPE_ECLIPSE_TEST_PLUGIN:
case PackagingType.TYPE_ECLIPSE_PLUGIN: {
actions.add(new BundlesAction(new File[] { basedir }));
break;
}
case PackagingType.TYPE_ECLIPSE_FEATURE: {
FeatureParser parser = new FeatureParser();
Feature feature = parser.parse(basedir);
Map<IInstallableUnit, Feature> featureMap = new HashMap<>();
FeaturesAction action = new FeaturesAction(new Feature[] { feature }) {
@Override
protected void publishFeatureArtifacts(Feature feature, IInstallableUnit featureIU,
IPublisherInfo publisherInfo) {
// so not call super as we don't wan't to copy anything --> Bug in P2 with
// IPublisherInfo.A_INDEX option
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=578380
}

@Override
protected IInstallableUnit generateFeatureJarIU(Feature feature, IPublisherInfo publisherInfo) {
IInstallableUnit iu = super.generateFeatureJarIU(feature, publisherInfo);
featureMap.put(iu, feature);
return iu;
}
};
actions.add(action);
break;
}
case PackagingType.TYPE_ECLIPSE_REPOSITORY: {
File categoryFile = new File(basedir, "category.xml");
if (categoryFile.exists()) {
try (InputStream stream = new FileInputStream(categoryFile)) {
SiteModel siteModel = new CategoryParser(null).parse(stream);
actions.add(new CategoryDependenciesAction(siteModel, project.getArtifactId(),
project.getVersion()));
} catch (IOException | SAXException e) {
throw new CoreException(Status.error("Error reading " + categoryFile.getAbsolutePath()));
}
}
for (File f : basedir.listFiles(File::isFile)) {
if (f.getName().endsWith(".product") && !f.getName().startsWith(".polyglot")) {
try {
IProductDescriptor productDescriptor = new ProductFile2(f.getAbsolutePath());
actions.add(new ProductDependenciesAction(productDescriptor));
} catch (Exception e) {
throw new CoreException(Status.error("Error reading " + f.getAbsolutePath()));
}
}
}
break;
}
default:
return Collections.emptyList();
}
if (actions.isEmpty()) {
List<IInstallableUnit> list = Collections.emptyList();
project.setContextValue(KEY_UNITS, list);
return list;
}
PublisherInfo publisherInfo = new PublisherInfo();
publisherInfo.setArtifactOptions(IPublisherInfo.A_INDEX);
PublisherResult results = new PublisherResult();
for (IPublisherAction action : actions) {
IStatus status = action.perform(publisherInfo, results, new NullProgressMonitor());
if (status.matches(IStatus.ERROR)) {
throw new CoreException(status);
}
}
Set<IInstallableUnit> result = Collections
.unmodifiableSet(results.query(QueryUtil.ALL_UNITS, null).toSet());
project.setContextValue(KEY_UNITS, result);
return result;

}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*******************************************************************************
* Copyright (c) 2008, 2011 Sonatype Inc. and others.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Sonatype Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.tycho.p2maven.actions;

import java.util.LinkedHashSet;
import java.util.Set;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.equinox.internal.p2.metadata.InstallableUnit;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.IProvidedCapability;
import org.eclipse.equinox.p2.metadata.IRequirement;
import org.eclipse.equinox.p2.metadata.MetadataFactory;
import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription;
import org.eclipse.equinox.p2.metadata.Version;
import org.eclipse.equinox.p2.metadata.VersionRange;
import org.eclipse.equinox.p2.publisher.AbstractPublisherAction;
import org.eclipse.equinox.p2.publisher.IPublisherInfo;
import org.eclipse.equinox.p2.publisher.IPublisherResult;
import org.eclipse.equinox.p2.publisher.PublisherResult;
import org.eclipse.equinox.spi.p2.publisher.PublisherHelper;

public abstract class AbstractDependenciesAction extends AbstractPublisherAction {

protected static final Version OSGi_versionMin = Version.createOSGi(0, 0, 0);

/**
* Conventional qualifier used to denote "ANY QUALIFIER" in feature.xml and .product files. See
* TYCHO-383.
*/
protected static final String ANY_QUALIFIER = "qualifier";

/**
* copy&paste from e3.5.1 org.eclipse.osgi.internal.resolver.StateImpl
*/
protected static final String OSGI_OS = "osgi.os";

/**
* copy&paste from e3.5.1 org.eclipse.osgi.internal.resolver.StateImpl
*/
protected static final String OSGI_WS = "osgi.ws";

/**
* copy&paste from e3.5.1 org.eclipse.osgi.internal.resolver.StateImpl
*/
protected static final String OSGI_ARCH = "osgi.arch";

/**
* copy&paste from e3.5.1 org.eclipse.osgi.internal.resolver.StateImpl
*/
protected static final String OSGI_NL = "osgi.nl";

protected static final String FEATURE_GROUP_IU_SUFFIX = ".feature.group";

protected void addRequiredCapability(Set<IRequirement> required, String id, Version version, String filter,
boolean optional) {
VersionRange range = getVersionRange(version);

required.add(MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, id, range,
InstallableUnit.parseFilter(filter), optional, false));
}

@Override
public IStatus perform(IPublisherInfo publisherInfo, IPublisherResult results, IProgressMonitor monitor) {
InstallableUnitDescription iud = new MetadataFactory.InstallableUnitDescription();
iud.setId(getId());
iud.setVersion(getVersion());

Set<IProvidedCapability> provided = new LinkedHashSet<>();
addProvidedCapabilities(provided);
provided.add(MetadataFactory.createProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, iud.getId(),
iud.getVersion()));
iud.addProvidedCapabilities(provided);

iud.addRequirements(getRequiredCapabilities());

addProperties(iud);
addPublisherAdvice(publisherInfo);

processCapabilityAdvice(iud, publisherInfo);
processInstallableUnitPropertiesAdvice(iud, publisherInfo);

IInstallableUnit iu = MetadataFactory.createInstallableUnit(iud);
results.addIU(iu, PublisherResult.ROOT);

InstallableUnitDescription[] others = processAdditionalInstallableUnitsAdvice(iu, publisherInfo);
if (others != null) {
for (InstallableUnitDescription other : others) {
// using PublisherResult.NON_ROOT results in these IUs appear after the primary
// see org.eclipse.equinox.p2.publisher.PublisherResult.getIUs(String, String)
// see org.eclipse.tycho.p2.metadata.IReactorArtifactFacade.getDependencyMetadata()
results.addIU(MetadataFactory.createInstallableUnit(other), PublisherResult.NON_ROOT);
}
}

return Status.OK_STATUS;
}

protected void addPublisherAdvice(IPublisherInfo publisherInfo) {
// do nothing by default
}

protected void addProperties(InstallableUnitDescription iud) {
// do nothing by default
}

protected abstract Set<IRequirement> getRequiredCapabilities();

protected void addProvidedCapabilities(Set<IProvidedCapability> provided) {

}

protected abstract Version getVersion();

protected abstract String getId();

protected VersionRange getVersionRange(String version) {
if (version == null) {
return VersionRange.emptyRange;
}

return getVersionRange(Version.create(version));
}

protected VersionRange getVersionRange(Version version) {
if (version == null || OSGi_versionMin.equals(version)) {
return VersionRange.emptyRange;
}

org.osgi.framework.Version osgiVersion = PublisherHelper.toOSGiVersion(version);

String qualifier = osgiVersion.getQualifier();

if (qualifier == null || "".equals(qualifier) || ANY_QUALIFIER.equals(qualifier)) {
Version from = Version.createOSGi(osgiVersion.getMajor(), osgiVersion.getMinor(), osgiVersion.getMicro());
Version to = Version.createOSGi(osgiVersion.getMajor(), osgiVersion.getMinor(), osgiVersion.getMicro() + 1);
return new VersionRange(from, true, to, false);
}

return new VersionRange(version, true, version, true);
}

protected Version createVersion(String version) {
return Version.create(version);
}

}
Loading

0 comments on commit e908004

Please sign in to comment.