From 542fe655dae5dc69ac7b419edc28b4a949f044c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Tue, 20 Feb 2024 17:11:43 +0100 Subject: [PATCH] Correctly consider cardinality based on the directives Currently the BundlesAction uses either 0 or 1 as the cardinality but actually a requirement can be a multi-cardinality as well. This adds new dedicated methods to not duplicate the computation and a testcase that ensures all combination are covered and correctly translated. --- .../p2/publisher/eclipse/BundlesAction.java | 33 ++++++++++++++----- .../publisher/actions/BundlesActionTest.java | 22 +++++++++++++ .../requireMultiple/META-INF/MANIFEST.MF | 9 +++++ 3 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 bundles/org.eclipse.equinox.p2.tests/testData/requireMultiple/META-INF/MANIFEST.MF 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 be1b87fa32..04c7558e49 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 @@ -398,10 +398,10 @@ protected void addRequirement(List reqsDeps, GenericSpecification Map directives = req.getDirectives(); String capFilter = directives.get(Namespace.REQUIREMENT_FILTER_DIRECTIVE); - boolean optional = directives.get(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE) == Namespace.RESOLUTION_OPTIONAL; - boolean greedy = optional ? INSTALLATION_GREEDY.equals(directives.get(INSTALLATION_DIRECTIVE)) : true; - - IRequirement requireCap = MetadataFactory.createRequirement(namespace, capFilter, null, optional ? 0 : 1, 1, + boolean greedy = isGreedy(directives); + int minCard = getMinCardinality(directives); + int maxCard = getMaxCardinality(directives); + IRequirement requireCap = MetadataFactory.createRequirement(namespace, capFilter, null, minCard, maxCard, greedy); reqsDeps.add(requireCap); } @@ -414,14 +414,31 @@ protected void addRequirement(List reqsDeps, GenericSpecification Map directives = req.getDirectives(); String capFilter = directives.get(Namespace.REQUIREMENT_FILTER_DIRECTIVE); - boolean optional = directives.get(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE) == Namespace.RESOLUTION_OPTIONAL; - boolean greedy = optional ? INSTALLATION_GREEDY.equals(directives.get(INSTALLATION_DIRECTIVE)) : true; - - IRequirement requireCap = MetadataFactory.createRequirement(namespace, capFilter, null, optional ? 0 : 1, 1, + boolean greedy = isGreedy(directives); + int minCard = getMinCardinality(directives); + int maxCard = getMaxCardinality(directives); + IRequirement requireCap = MetadataFactory.createRequirement(namespace, capFilter, null, minCard, maxCard, greedy, bd.getSymbolicName()); reqsDeps.add(requireCap); } + protected int getMinCardinality(Map directives) { + return Namespace.RESOLUTION_OPTIONAL.equals(directives.get(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE)) ? 0 : 1; + } + + protected int getMaxCardinality(Map directives) { + return Namespace.CARDINALITY_MULTIPLE.equals(directives.get(Namespace.REQUIREMENT_CARDINALITY_DIRECTIVE)) + ? Integer.MAX_VALUE + : 1; + } + + protected boolean isGreedy(Map directives) { + if (getMinCardinality(directives) == 0) { + return INSTALLATION_GREEDY.equals(directives.get(INSTALLATION_DIRECTIVE)); + } + return true; + } + protected void addCapability(List caps, GenericDescription provideCapDesc, InstallableUnitDescription iu, int capNo) { // Convert the values to String, Version, List of String or Version diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/BundlesActionTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/BundlesActionTest.java index 03f7249a5f..8109bb5d57 100644 --- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/BundlesActionTest.java +++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/BundlesActionTest.java @@ -48,6 +48,7 @@ import org.eclipse.equinox.internal.p2.metadata.ArtifactKey; import org.eclipse.equinox.internal.p2.metadata.OSGiVersion; import org.eclipse.equinox.internal.p2.metadata.RequiredCapability; +import org.eclipse.equinox.internal.p2.metadata.RequiredPropertiesMatch; import org.eclipse.equinox.internal.p2.metadata.TranslationSupport; import org.eclipse.equinox.p2.metadata.IArtifactKey; import org.eclipse.equinox.p2.metadata.IInstallableUnit; @@ -515,6 +516,27 @@ public void testPublishBundlesWhereOneBundleIsInvalid() throws Exception { assertThat(ius.size(), is(1)); } + public void testMultiRequired() throws Exception { + File testData = new File(TestActivator.getTestDataFolder(), "requireMultiple"); + IInstallableUnit iu = BundlesAction.createBundleIU(BundlesAction.createBundleDescription(testData), null, + new PublisherInfo()); + Map> map = iu.getRequirements().stream() + .filter(RequiredPropertiesMatch.class::isInstance) + .map(RequiredPropertiesMatch.class::cast) + .collect(Collectors.groupingBy(m -> RequiredPropertiesMatch.extractNamespace(m.getMatches()))); + assertCardinality(map.get("single.required"), 1, 1); + assertCardinality(map.get("single.optional"), 0, 1); + assertCardinality(map.get("multiple.required"), 1, Integer.MAX_VALUE); + assertCardinality(map.get("multiple.optional"), 0, Integer.MAX_VALUE); + } + + protected void assertCardinality(List matches, int min, int max) { + assertNotNull(matches); + assertEquals(1, matches.size()); + assertEquals(min, matches.get(0).getMin()); + assertEquals(max, matches.get(0).getMax()); + } + public void testMultiVersionCapability() throws Exception { File testData = getTestData("dymamicImport", "testData/multiVersionCapability/bundle1"); IInstallableUnit iu = BundlesAction.createBundleIU(BundlesAction.createBundleDescription(testData), null, diff --git a/bundles/org.eclipse.equinox.p2.tests/testData/requireMultiple/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.tests/testData/requireMultiple/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..b9fda57f13 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.tests/testData/requireMultiple/META-INF/MANIFEST.MF @@ -0,0 +1,9 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: require.multiple +Bundle-SymbolicName: require.multiple +Bundle-Version: 1.0.0 +Require-Capability: single.required;filter:="(objectClass=testme)", + single.optional;filter:="(objectClass=testme)";resolution:=optional, + multiple.required;filter:="(objectClass=testme)";cardinality:=multiple, + multiple.optional;filter:="(objectClass=testme)";cardinality:=multiple;resolution:=optional