blob: 7259e4d3d6b7922a8dc085636cabbf2de815b9fe [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2017 SSI Schaefer IT Solutions GmbH 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* SSI Schaefer IT Solutions GmbH
*******************************************************************************/
package org.eclipse.tea.library.build.p2;
import java.io.File;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.equinox.frameworkadmin.BundleInfo;
import org.eclipse.equinox.internal.p2.publisher.eclipse.IProductDescriptor;
import org.eclipse.equinox.internal.provisional.frameworkadmin.ConfigData;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.IVersionedId;
import org.eclipse.equinox.p2.publisher.IPublisherAction;
import org.eclipse.equinox.p2.publisher.IPublisherInfo;
import org.eclipse.equinox.p2.publisher.IPublisherResult;
import org.eclipse.equinox.p2.publisher.PublisherInfo;
import org.eclipse.equinox.p2.publisher.PublisherResult;
import org.eclipse.equinox.p2.publisher.eclipse.ConfigAdvice;
import org.eclipse.equinox.p2.publisher.eclipse.EquinoxLauncherCUAction;
import org.eclipse.equinox.p2.publisher.eclipse.ProductAction;
import org.eclipse.equinox.p2.query.IQuery;
import org.eclipse.equinox.p2.query.QueryUtil;
import org.eclipse.pde.internal.build.IPDEBuildConstants;
/**
* Publishes a product definition to the update site.
* <p>
* When publishing a product together with other bundles and features to an
* update site the original implementation adds dependencies against all bundles
* to the product and so the product will fail to install. This version is taken
* from buckminster in order to prevent this.
* </p>
* <p>
* A configuration advice for the required bundles to startup equinox is added
* to the publisher so that the configuration file is written correctly when
* installing the product
* </p>
* <p>
* The branding of the executables has troubles if the projects are not directly
* inside of the workspace
* </p>
*/
@SuppressWarnings("restriction")
public class TeaProductAction extends ProductAction implements IPDEBuildConstants {
private final File platformExecutables;
private final File overrideExecutables;
/**
* Creates a new product publishing action
*
* @param product
* the product to publish
* @param executables
* the location of the feature containing the executables
*/
public TeaProductAction(IProductDescriptor product, File executables, File overrideExecutables) {
super(null, product, "tooling", executables);
this.platformExecutables = executables;
this.overrideExecutables = overrideExecutables;
}
@Override
public IStatus perform(IPublisherInfo info, IPublisherResult results, IProgressMonitor monitor) {
final IPublisherResult innerResult = new PublisherResult();
// we are creating a separate publisher information for the
// product publishing as otherwise the resulting product
// will have a dependency against every published bundle
final PublisherInfo innerInfo = new PublisherInfo();
innerInfo.setConfigurations(info.getConfigurations());
innerInfo.setArtifactOptions(info.getArtifactOptions());
innerInfo.setArtifactRepository(info.getArtifactRepository());
innerInfo.setMetadataRepository(info.getMetadataRepository());
innerInfo.setContextArtifactRepository(info.getContextArtifactRepository());
innerInfo.setContextMetadataRepository(info.getContextMetadataRepository());
// build up caches containing the required information indexed by the id
final Map<String, BundleInfo> defaultBundles = getDefaultBundles();
final Map<String, BundleInfo> productBundleInfos = getBundleInfos(product);
// The publishing result for the product must see the following elements
// * Launcher - Required to generate the correct configuration and
// branding
// * Default Bundles - Required in order to startup equinox
// * Root Elements - The elements that make the product in order to
// determine the version
final ConfigData defaultStartInfos = new ConfigData(null, null, null, null);
for (IInstallableUnit iu : results.getIUs(null, IPublisherResult.ROOT)) {
final String symbolicId = iu.getId();
// launchers must be added to the publisher so that the
// ApplicationLauncherAction can
// generate the correct configuration
if (symbolicId.startsWith(EquinoxLauncherCUAction.ORG_ECLIPSE_EQUINOX_LAUNCHER)) {
innerResult.addIU(iu, IPublisherResult.ROOT);
continue;
}
// publish the default bundles
final BundleInfo defaultBundle = defaultBundles.get(symbolicId);
if (defaultBundle != null) {
innerResult.addIU(iu, IPublisherResult.ROOT);
defaultStartInfos.addBundle(defaultBundle);
}
// Check if we have a custom configuration for the given bundle
final BundleInfo productBundle = productBundleInfos.get(symbolicId);
if (productBundle != null) {
innerResult.addIU(iu, IPublisherResult.ROOT);
}
}
// add all root elements of the product so that
// the correct version can be determined during the publishing
for (IVersionedId feature : product.getFeatures()) {
String featureId = feature.getId() + ".feature.group";
IQuery<IInstallableUnit> iuQuery = QueryUtil.createIUQuery(featureId);
Iterator<IInstallableUnit> itor = results.query(iuQuery, monitor).iterator();
while (itor.hasNext()) {
innerResult.addIU(itor.next(), IPublisherResult.ROOT);
}
}
// add a configuration advice for the default bundles
Assert.isLegal(defaultStartInfos.getBundles().length > 0, "Default bundles not found");
for (String configSpec : innerInfo.getConfigurations()) {
innerInfo.addAdvice(new ConfigAdvice(defaultStartInfos, configSpec));
}
// perform the publishing with the given configuration and return the
// merged result
final IStatus status = super.perform(innerInfo, innerResult, monitor);
if (status.getSeverity() != IStatus.ERROR) {
results.merge(innerResult, IPublisherResult.MERGE_MATCHING);
}
return status;
}
@Override
protected IPublisherAction createApplicationExecutableAction(String[] configSpecs) {
return new TeaApplicationLauncherAction(id, version, flavor, executableName, platformExecutables, configSpecs,
overrideExecutables);
}
/**
* Returns a indexed map of bundles required to startup the equinox
* framework
*/
private static Map<String, BundleInfo> getDefaultBundles() {
final Map<String, BundleInfo> bundles = new TreeMap<>();
{
String bundleId = BUNDLE_SIMPLE_CONFIGURATOR;
bundles.put(bundleId, new BundleInfo(bundleId, null, null, 1, true));
}
{
String bundleId = BUNDLE_EQUINOX_COMMON;
bundles.put(bundleId, new BundleInfo(bundleId, null, null, 2, true));
}
{
String bundleId = BUNDLE_OSGI;
bundles.put(bundleId, new BundleInfo(bundleId, null, null, -1, true));
}
{
String bundleId = BUNDLE_CORE_RUNTIME;
bundles.put(bundleId, new BundleInfo(bundleId, null, null, 4, true));
}
{
String bundleId = BUNDLE_DS;
bundles.put(bundleId, new BundleInfo(bundleId, null, null, 2, true));
}
return bundles;
}
/** Returns a indexed map of bundles that have a custom configuration */
private static Map<String, BundleInfo> getBundleInfos(IProductDescriptor product) {
final Map<String, BundleInfo> bundles = new TreeMap<>();
for (BundleInfo bundleInfo : product.getBundleInfos()) {
bundles.put(bundleInfo.getSymbolicName(), bundleInfo);
}
return bundles;
}
}