diff options
author | Christoph Läubrich | 2021-08-06 17:37:50 +0000 |
---|---|---|
committer | Mickael Istria | 2021-08-12 14:22:07 +0000 |
commit | bbf39de583c4b7e8b1ddc6c1b2e0d934deab8391 (patch) | |
tree | 73f72699cbe085612a53d0bc7100fe36cd366ec1 | |
parent | 789375713ce6f39b4c0354501e1b0a84cc8c8c41 (diff) | |
download | rt.equinox.p2-bbf39de583c4b7e8b1ddc6c1b2e0d934deab8391.tar.gz rt.equinox.p2-bbf39de583c4b7e8b1ddc6c1b2e0d934deab8391.tar.xz rt.equinox.p2-bbf39de583c4b7e8b1ddc6c1b2e0d934deab8391.zip |
Bug 574952 - p2 should distinguish between "product plugins" and
"configuration plugins"
- refactor ProductFileAdvice to keep a separate list of configuration
only bundles while building the config data
Change-Id: I667864e4be2c87b35ee37e18c15aabb120785d1d
Signed-off-by: Christoph Läubrich <laeubi@laeubi-soft.de>
Reviewed-on: https://git.eclipse.org/r/c/equinox/rt.equinox.p2/+/183795
Tested-by: Equinox Bot <equinox-bot@eclipse.org>
Reviewed-by: Mickael Istria <mistria@redhat.com>
5 files changed, 118 insertions, 103 deletions
diff --git a/bundles/org.eclipse.equinox.p2.publisher.eclipse/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.publisher.eclipse/META-INF/MANIFEST.MF index 1bb6b0025..049dcc704 100644 --- a/bundles/org.eclipse.equinox.p2.publisher.eclipse/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.equinox.p2.publisher.eclipse/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %bundleName Bundle-SymbolicName: org.eclipse.equinox.p2.publisher.eclipse;singleton:=true -Bundle-Version: 1.4.0.qualifier +Bundle-Version: 1.4.1.qualifier Bundle-Activator: org.eclipse.pde.internal.publishing.Activator Bundle-ActivationPolicy: lazy Bundle-Vendor: %providerName diff --git a/bundles/org.eclipse.equinox.p2.publisher.eclipse/pom.xml b/bundles/org.eclipse.equinox.p2.publisher.eclipse/pom.xml index 35c78d3a3..4104aa709 100644 --- a/bundles/org.eclipse.equinox.p2.publisher.eclipse/pom.xml +++ b/bundles/org.eclipse.equinox.p2.publisher.eclipse/pom.xml @@ -10,6 +10,6 @@ <groupId>org.eclipse.equinox</groupId> <artifactId>org.eclipse.equinox.p2.publisher.eclipse</artifactId> - <version>1.4.0-SNAPSHOT</version> + <version>1.4.1-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> </project> diff --git a/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/p2/publisher/eclipse/BundlesAction.java b/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/p2/publisher/eclipse/BundlesAction.java index f4199cf52..f05207712 100644 --- a/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/p2/publisher/eclipse/BundlesAction.java +++ b/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/p2/publisher/eclipse/BundlesAction.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2018 Code 9 and others. + * Copyright (c) 2008, 2021 Code 9 and others. * * This * program and the accompanying materials are made available under the terms of @@ -14,6 +14,7 @@ * IBM - ongoing development * SAP AG - make optional dependencies non-greedy by default; allow setting greedy through directive (bug 247099) * Red Hat Inc. - Bug 460967 + * Christoph Läubrich - Bug 574952 p2 should distinguish between "product plugins" and "configuration plugins" (gently sponsored by Compart AG) ******************************************************************************/ package org.eclipse.equinox.p2.publisher.eclipse; @@ -136,6 +137,13 @@ public class BundlesAction extends AbstractPublisherAction { public static IInstallableUnit createBundleConfigurationUnit(String hostId, Version cuVersion, boolean isBundleFragment, GeneratorBundleInfo configInfo, String configurationFlavor, IMatchExpression<IInstallableUnit> filter) { + return createBundleConfigurationUnit(hostId, cuVersion, isBundleFragment, configInfo, configurationFlavor, + filter, false); + } + + static IInstallableUnit createBundleConfigurationUnit(String hostId, Version cuVersion, + boolean isBundleFragment, GeneratorBundleInfo configInfo, String configurationFlavor, + IMatchExpression<IInstallableUnit> filter, boolean configOnly) { if (configInfo == null) return null; @@ -145,7 +153,7 @@ public class BundlesAction extends AbstractPublisherAction { cu.setVersion(cuVersion); // Indicate the IU to which this CU apply - Version hostVersion = Version.parseVersion(configInfo.getVersion()); + Version hostVersion = configOnly ? Version.emptyVersion : Version.parseVersion(configInfo.getVersion()); VersionRange range = hostVersion == Version.emptyVersion ? VersionRange.emptyRange : new VersionRange(hostVersion, true, Version.MAX_VERSION, true); cu.setHost(new IRequirement[] { // diff --git a/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/p2/publisher/eclipse/ConfigCUsAction.java b/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/p2/publisher/eclipse/ConfigCUsAction.java index 823000c2b..ba349e047 100644 --- a/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/p2/publisher/eclipse/ConfigCUsAction.java +++ b/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/p2/publisher/eclipse/ConfigCUsAction.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2017 Code 9 and others. + * Copyright (c) 2008, 2021 Code 9 and others. * * This * program and the accompanying materials are made available under the terms of @@ -13,12 +13,14 @@ * Code 9 - initial API and implementation * IBM - ongoing development * Rapicorp - ongoing development + * Christoph Läubrich - Bug 574952 p2 should distinguish between "product plugins" and "configuration plugins" (gently sponsored by Compart AG) ******************************************************************************/ package org.eclipse.equinox.p2.publisher.eclipse; import java.io.File; import java.util.*; import java.util.Map.Entry; +import java.util.stream.Collectors; import org.eclipse.core.runtime.*; import org.eclipse.equinox.frameworkadmin.BundleInfo; import org.eclipse.equinox.internal.p2.metadata.TouchpointInstruction; @@ -106,7 +108,12 @@ public class ConfigCUsAction extends AbstractPublisherAction { String configSpec = configSpec1; Collection<IConfigAdvice> configAdvice = publisherInfo.getAdvice(configSpec, false, id, version, IConfigAdvice.class); BundleInfo[] bundles = fillInBundles(configAdvice, results); - publishBundleCUs(publisherInfo, bundles, configSpec, innerResult); + Set<String> configBundles = configAdvice.stream().filter(ProductFileAdvice.class::isInstance) + .map(ProductFileAdvice.class::cast).flatMap(pca -> pca.getBundles(true)) + .map(BundleInfo::getSymbolicName).filter(Objects::nonNull) + .distinct() + .collect(Collectors.toSet()); + publishBundleCUs(publisherInfo, bundles, configSpec, innerResult, configBundles); publishConfigIUs(configAdvice, innerResult, configSpec); Collection<IExecutableAdvice> launchingAdvice = publisherInfo.getAdvice(configSpec, false, id, version, IExecutableAdvice.class); publishIniIUs(launchingAdvice, innerResult, configSpec); @@ -324,10 +331,13 @@ public class ConfigCUsAction extends AbstractPublisherAction { } /** - * Publish the CUs related to the given set of bundles. This generally covers the start-level and - * and whether or not the bundle is to be started. + * Publish the CUs related to the given set of bundles. This generally covers + * the start-level and and whether or not the bundle is to be started. + * + * @param configBundles */ - protected void publishBundleCUs(IPublisherInfo publisherInfo, BundleInfo[] bundles, String configSpec, IPublisherResult result) { + protected void publishBundleCUs(IPublisherInfo publisherInfo, BundleInfo[] bundles, String configSpec, + IPublisherResult result, Set<String> configBundles) { if (bundles == null) return; @@ -338,24 +348,28 @@ public class ConfigCUsAction extends AbstractPublisherAction { filter = createFilterSpec(configSpec); } - for (BundleInfo bundle1 : bundles) { - GeneratorBundleInfo bundle = createGeneratorBundleInfo(bundle1, result); - if (bundle == null) + for (BundleInfo bundleInfo : bundles) { + GeneratorBundleInfo generatorBundle = createGeneratorBundleInfo(bundleInfo, result); + if (generatorBundle == null) continue; - IInstallableUnit iu = bundle.getIU(); + IInstallableUnit iu = generatorBundle.getIU(); // If there is no host, or the filters don't match, skip this one. if (iu == null || !filterMatches(iu.getFilter(), configSpec)) continue; - if (bundle.getStartLevel() == BundleInfo.NO_LEVEL && !bundle.isMarkedAsStarted()) { + if (generatorBundle.getStartLevel() == BundleInfo.NO_LEVEL && !generatorBundle.isMarkedAsStarted()) { // this bundle does not require any particular configuration, the plug-in // default IU will handle installing it continue; } - IInstallableUnit cu = null; - if (this.version != null && !this.version.equals(Version.emptyVersion)) - cu = BundlesAction.createBundleConfigurationUnit(bundle.getSymbolicName(), this.version, false, bundle, flavor + cuIdPrefix, filter); - else - cu = BundlesAction.createBundleConfigurationUnit(bundle.getSymbolicName(), Version.parseVersion(bundle.getVersion()), false, bundle, flavor + cuIdPrefix, filter); + IInstallableUnit cu; + if (configBundles.contains(bundleInfo.getSymbolicName())) { + cu = BundlesAction.createBundleConfigurationUnit(generatorBundle.getSymbolicName(), this.version, false, generatorBundle, + flavor + cuIdPrefix, filter, true); + } else if (this.version != null && !this.version.equals(Version.emptyVersion)) { + cu = BundlesAction.createBundleConfigurationUnit(generatorBundle.getSymbolicName(), this.version, false, generatorBundle, flavor + cuIdPrefix, filter); + } else { + cu = BundlesAction.createBundleConfigurationUnit(generatorBundle.getSymbolicName(), Version.parseVersion(generatorBundle.getVersion()), false, generatorBundle, flavor + cuIdPrefix, filter); + } if (cu != null) { // Product Query will run against the repo, make sure these CUs are in before then // TODO review the aggressive addition to the metadata repo. perhaps the query can query the result as well. diff --git a/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/p2/publisher/eclipse/ProductFileAdvice.java b/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/p2/publisher/eclipse/ProductFileAdvice.java index 551796a7a..19258375b 100644 --- a/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/p2/publisher/eclipse/ProductFileAdvice.java +++ b/bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/p2/publisher/eclipse/ProductFileAdvice.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2017 Code 9 and others. + * Copyright (c) 2008, 2021 Code 9 and others. * * This * program and the accompanying materials are made available under the terms of @@ -14,11 +14,14 @@ * EclipseSource - ongoing development * IBM Corporation - ongoing development * Rapicorp - additional features + * Christoph Läubrich - Bug 574952 p2 should distinguish between "product plugins" and "configuration plugins" (gently sponsored by Compart AG) ******************************************************************************/ package org.eclipse.equinox.p2.publisher.eclipse; import java.io.File; import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.eclipse.equinox.frameworkadmin.BundleInfo; import org.eclipse.equinox.internal.p2.core.helpers.CollectionUtils; import org.eclipse.equinox.internal.p2.publisher.eclipse.DataLoader; @@ -32,10 +35,11 @@ import org.eclipse.equinox.p2.publisher.actions.ILicenseAdvice; import org.eclipse.equinox.p2.repository.IRepositoryReference; /** - * Provide advice derived from the .product file. The product can give some info on - * launching as well as the configuration (bundles, properties, ...) + * Provide advice derived from the .product file. The product can give some info + * on launching as well as the configuration (bundles, properties, ...) */ -public class ProductFileAdvice extends AbstractAdvice implements ILicenseAdvice, IExecutableAdvice, IConfigAdvice, IBrandingAdvice { +public class ProductFileAdvice extends AbstractAdvice + implements ILicenseAdvice, IExecutableAdvice, IConfigAdvice, IBrandingAdvice { private final static String OSGI_SPLASH_PATH = "osgi.splashPath"; //$NON-NLS-1$ private final static String SPLASH_PREFIX = "platform:/base/plugins/"; //$NON-NLS-1$ private final IProductDescriptor product; @@ -43,7 +47,7 @@ public class ProductFileAdvice extends AbstractAdvice implements ILicenseAdvice, private String ws; private String os; private String arch; - private ConfigData configData = null; + private final ProductConfigData configData; @Override protected String getId() { @@ -56,12 +60,9 @@ public class ProductFileAdvice extends AbstractAdvice implements ILicenseAdvice, } /** - * Constructs a new ProductFileAdvice for a given product file and a - * particular configuration. Configurations are - * specified as: ws.os.arch where: - * ws is the windowing system - * os is the operating system - * arch is the architecture + * Constructs a new ProductFileAdvice for a given product file and a particular + * configuration. Configurations are specified as: ws.os.arch where: ws is the + * windowing system os is the operating system arch is the architecture */ public ProductFileAdvice(IProductDescriptor product, String configSpec) { this.product = product; @@ -82,7 +83,7 @@ public class ProductFileAdvice extends AbstractAdvice implements ILicenseAdvice, } /** - * Returns the program arguments for this product. + * Returns the program arguments for this product. */ @Override public String[] getProgramArguments() { @@ -99,32 +100,34 @@ public class ProductFileAdvice extends AbstractAdvice implements ILicenseAdvice, return AbstractPublisherAction.getArrayFromString(line, " "); //$NON-NLS-1$ } - /** - * Returns the Bundles that constitute this product. These - * bundles may be specified in the .product file, .product file configuration - * area, config.ini file, or a combination of these three places. - */ @Override public BundleInfo[] getBundles() { - return configData.getBundles(); + return Stream.concat(getBundles(false), getBundles(true)) + .toArray(BundleInfo[]::new); + } + + Stream<BundleInfo> getBundles(boolean configOnly) { + if (configOnly) { + return configData.configBundles.stream(); + } + return Arrays.stream(configData.data.getBundles()); } /** - * Returns the properties associated with this product. These - * properties may be defined in the .product file, the config.ini - * file, or both. + * Returns the properties associated with this product. These properties may be + * defined in the .product file, the config.ini file, or both. */ @Override public Map<String, String> getProperties() { Map<String, String> result = new HashMap<>(); - CollectionUtils.putAll(configData.getProperties(), result); + CollectionUtils.putAll(configData.data.getProperties(), result); result.putAll(product.getConfigurationProperties(os, arch)); return result; } /** - * Returns the name of the launcher. This should be the OS-independent - * name. That is, ".exe" etc. should not be included. + * Returns the name of the launcher. This should be the OS-independent name. + * That is, ".exe" etc. should not be included. * * @return the name of the branded launcher or <code>null</code> if none. */ @@ -179,16 +182,18 @@ public class ProductFileAdvice extends AbstractAdvice implements ILicenseAdvice, return product.getRepositoryEntries(); } - private ConfigData getConfigData() { + private ProductConfigData getConfigData() { DataLoader loader = createDataLoader(); ConfigData result; if (loader != null) { result = loader.getConfigData(); - } else + } else { result = generateConfigData(); - - addProductFileBundles(result); // these are the bundles specified in the <plugins/> tag - addProductFileConfigBundles(result); // these are the bundles specified in the <configurations> tag in the product file + } + ProductConfigData data = new ProductConfigData(result); + addProductFileBundles(data); // these are the bundles specified in the <plugins/> tag + addProductFileConfigBundles(data); // these are the bundles specified in the <configurations> tag in the + // product file if (product.getProductId() != null) result.setProperty("eclipse.product", product.getProductId()); //$NON-NLS-1$ if (product.getApplication() != null) @@ -196,70 +201,42 @@ public class ProductFileAdvice extends AbstractAdvice implements ILicenseAdvice, String location = getSplashLocation(); if (location != null) result.setProperty(OSGI_SPLASH_PATH, SPLASH_PREFIX + location); - return result; + return data; } - private void addProductFileConfigBundles(ConfigData data) { - Set<BundleInfo> versionBoundBundles = new HashSet<>(); - Map<String, List<BundleInfo>> unboundedBundles = new HashMap<>(); - - BundleInfo[] bundles = data.getBundles(); - for (BundleInfo bundleInfo : bundles) { - // For each bundle we know about, cache it. If the bundle doesn't have a version - // add it to a list of bundles by name - if (bundleInfo.getVersion().equals(BundleInfo.EMPTY_VERSION)) { - addUnboundedBundle(unboundedBundles, bundleInfo); + private void addProductFileConfigBundles(ProductConfigData productConfigData) { + Map<String, List<BundleInfo>> configBundleMap = Arrays.stream(productConfigData.data.getBundles()) + .collect(Collectors.groupingBy(BundleInfo::getSymbolicName)); + for (BundleInfo configBundleInfo : product.getBundleInfos()) { + List<BundleInfo> matches = configBundleMap.get(configBundleInfo.getSymbolicName()); + if (matches == null || matches.isEmpty()) { + // if there is no match in the ConfigData (e.g. plugin or mixed type product) + // simply add this to the list of config bundles + productConfigData.configBundles.add(configBundleInfo); } else { - versionBoundBundles.add(bundleInfo); - addUnboundedBundle(unboundedBundles, bundleInfo); + // otherwise just update the existing data + for (BundleInfo target : matches) { + target.setStartLevel(configBundleInfo.getStartLevel()); + target.setMarkedAsStarted(configBundleInfo.isMarkedAsStarted()); + } } } - - List<BundleInfo> bundleInfos = product.getBundleInfos(); - for (BundleInfo bundleInfo : bundleInfos) { - // For each bundle that has configuration information, if the bundle is in the - // bundles bound by version, add the "configured" bundle instead - // If the bundle is not bound to a version, then replace all bounded versions - // with this one. Otherwise, just add this one (don't replace) - if (versionBoundBundles.contains(bundleInfo)) { - // If we found a version with the same name and version, replace it with the "configured" bundle - data.removeBundle(bundleInfo); - data.addBundle(bundleInfo); - } else if (bundleInfo.getVersion().equals(BundleInfo.EMPTY_VERSION)) { - // If we don't have a version number, look for all bundles that match by name - List<BundleInfo> list = unboundedBundles.get(bundleInfo.getSymbolicName()); - if (list == null) - data.addBundle(bundleInfo); - else - for (BundleInfo target : list) { - target.setStartLevel(bundleInfo.getStartLevel()); - target.setMarkedAsStarted(bundleInfo.isMarkedAsStarted()); - } - } else { - // Otherwise we have a version, but we could not match it, so just add this one. - data.addBundle(bundleInfo); - } - - } - } - - private void addUnboundedBundle(Map<String, List<BundleInfo>> data, BundleInfo bundleInfo) { - if (!data.containsKey(bundleInfo.getSymbolicName())) - data.put(bundleInfo.getSymbolicName(), new LinkedList<BundleInfo>()); - data.get(bundleInfo.getSymbolicName()).add(bundleInfo); } - private void addProductFileBundles(ConfigData data) { + private void addProductFileBundles(ProductConfigData productConfigData) { + if (product.useFeatures()) { + return; + } List<IVersionedId> bundles = product.getBundles(true); Set<BundleInfo> set = new HashSet<>(); - set.addAll(Arrays.asList(data.getBundles())); + set.addAll(Arrays.asList(productConfigData.data.getBundles())); for (IVersionedId vid : bundles) { BundleInfo bundleInfo = new BundleInfo(); bundleInfo.setSymbolicName(vid.getId()); bundleInfo.setVersion(vid.getVersion().toString()); if (!set.contains(bundleInfo)) - data.addBundle(bundleInfo); + productConfigData.data.addBundle(bundleInfo); } } @@ -268,7 +245,7 @@ public class ProductFileAdvice extends AbstractAdvice implements ILicenseAdvice, if (product.useFeatures()) return result; - // Add all the bundles here. We replace / update them later + // Add all the bundles here. We replace / update them later // if we find configuration information List<IVersionedId> bundles = product.getBundles(true); for (IVersionedId vid : bundles) { @@ -295,21 +272,24 @@ public class ProductFileAdvice extends AbstractAdvice implements ILicenseAdvice, String targetWS = AbstractPublisherAction.parseConfigSpec(spec)[0]; if (targetWS == null) targetWS = AbstractPublisherAction.CONFIG_ANY; - if (!ws.equals(targetWS) && !ws.equals(AbstractPublisherAction.CONFIG_ANY) && !targetWS.equals(AbstractPublisherAction.CONFIG_ANY)) { + if (!ws.equals(targetWS) && !ws.equals(AbstractPublisherAction.CONFIG_ANY) + && !targetWS.equals(AbstractPublisherAction.CONFIG_ANY)) { return false; } String targetOS = AbstractPublisherAction.parseConfigSpec(spec)[1]; if (targetOS == null) targetOS = AbstractPublisherAction.CONFIG_ANY; - if (!os.equals(targetOS) && !os.equals(AbstractPublisherAction.CONFIG_ANY) && !targetOS.equals(AbstractPublisherAction.CONFIG_ANY)) { + if (!os.equals(targetOS) && !os.equals(AbstractPublisherAction.CONFIG_ANY) + && !targetOS.equals(AbstractPublisherAction.CONFIG_ANY)) { return false; } String targetArch = AbstractPublisherAction.parseConfigSpec(spec)[2]; if (targetArch == null) targetArch = AbstractPublisherAction.CONFIG_ANY; - if (!arch.equals(targetArch) && !arch.equals(AbstractPublisherAction.CONFIG_ANY) && !targetArch.equals(AbstractPublisherAction.CONFIG_ANY)) { + if (!arch.equals(targetArch) && !arch.equals(AbstractPublisherAction.CONFIG_ANY) + && !targetArch.equals(AbstractPublisherAction.CONFIG_ANY)) { return false; } } @@ -325,16 +305,29 @@ public class ProductFileAdvice extends AbstractAdvice implements ILicenseAdvice, File configFile = new File(location); // We are assuming we are always relative from the product file - // However PDE tooling puts us relative from the workspace, that "relative" path also looks like an absolute path on linux + // However PDE tooling puts us relative from the workspace, that "relative" path + // also looks like an absolute path on linux // Build may have copied the file to the correct place for us if (!configFile.isAbsolute() || !configFile.exists()) configFile = new File(product.getLocation().getParentFile(), location); - //We don't really have an executable location, get something reasonable based on the config.ini location + // We don't really have an executable location, get something reasonable based + // on the config.ini location File parent = configFile.getParentFile(); if (parent.getName().equals("configuration") && parent.getParentFile() != null) //$NON-NLS-1$ parent = parent.getParentFile(); return new DataLoader(configFile, parent); } + private static final class ProductConfigData { + + private final List<BundleInfo> configBundles = new ArrayList<>(); + private final ConfigData data; + + public ProductConfigData(ConfigData data) { + this.data = data; + } + + } + } |