Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Kurtakov2018-01-22 22:18:39 +0000
committerAlexander Kurtakov2018-01-22 22:20:00 +0000
commitb5fe42dfc2ca68d6153010efb901560e415c6dad (patch)
treec946170860538c0e28de5dd809921945db34d7a7
parent0e3caa9359428dcb20c1dc3a2c580fff64777d3d (diff)
downloadrt.equinox.p2-b5fe42dfc2ca68d6153010efb901560e415c6dad.tar.gz
rt.equinox.p2-b5fe42dfc2ca68d6153010efb901560e415c6dad.tar.xz
rt.equinox.p2-b5fe42dfc2ca68d6153010efb901560e415c6dad.zip
Revert "Revert "Bug 528387 - Dedicated xml elements for genericI20180122-2000
requirements"" This reverts commit 0e3caa9359428dcb20c1dc3a2c580fff64777d3d. Change-Id: Ifafe2feedb963b90f54a19b2e08a49d3b18d475a Signed-off-by: Alexander Kurtakov <akurtako@redhat.com>
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/MetadataRepositoryIO.java2
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/MetadataParser.java250
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/MetadataWriter.java121
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/XMLConstants.java32
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ProvidedCapability.java125
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredCapability.java51
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredPropertiesMatch.java84
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/Requirement.java14
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/expression/CoercingComparator.java4
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/index/CapabilityIndex.java4
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/messages.properties2
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/IProvidedCapability.java39
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/MetadataFactory.java137
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher.eclipse/META-INF/MANIFEST.MF2
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher.eclipse/src/org/eclipse/equinox/p2/publisher/eclipse/BundlesAction.java91
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/AbstractPublisherAction.java2
-rw-r--r--bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/persistence/XMLConstants.java16
-rw-r--r--bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/persistence/XMLWriter.java82
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/director/AutomatedDirectorTest.java255
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/engine/PhaseSetTest.java33
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/RequirementToString.java13
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/expression/AllTests.java9
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/expression/FilterTest.java439
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/repository/SPIMetadataRepositoryTest.java20
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/PropertyMatchRequirement.java111
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/ActionTest.java23
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/BundlesActionTest.java109
27 files changed, 1315 insertions, 755 deletions
diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/MetadataRepositoryIO.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/MetadataRepositoryIO.java
index ed67c081a..4243ad59d 100644
--- a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/MetadataRepositoryIO.java
+++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/MetadataRepositoryIO.java
@@ -104,7 +104,7 @@ public class MetadataRepositoryIO {
// A format version number for metadata repository XML.
public static final Version COMPATIBLE_VERSION = Version.createOSGi(1, 0, 0);
- public static final Version CURRENT_VERSION = Version.createOSGi(1, 1, 0);
+ public static final Version CURRENT_VERSION = Version.createOSGi(1, 2, 0);
public static final VersionRange XML_TOLERANCE = new VersionRange(COMPATIBLE_VERSION, true, Version.createOSGi(2, 0, 0), false);
// Constants for processing Instructions
diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/MetadataParser.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/MetadataParser.java
index 20fc56a8d..024631745 100644
--- a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/MetadataParser.java
+++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/MetadataParser.java
@@ -12,11 +12,14 @@
*******************************************************************************/
package org.eclipse.equinox.internal.p2.metadata.repository.io;
+import static java.util.stream.Collectors.toList;
+
import java.net.URI;
import java.util.*;
import java.util.Map.Entry;
import org.eclipse.equinox.internal.p2.core.helpers.OrderedProperties;
-import org.eclipse.equinox.internal.p2.metadata.*;
+import org.eclipse.equinox.internal.p2.metadata.ArtifactKey;
+import org.eclipse.equinox.internal.p2.metadata.InstallableUnit;
import org.eclipse.equinox.internal.p2.persistence.XMLParser;
import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.metadata.MetadataFactory.*;
@@ -30,18 +33,6 @@ import org.xml.sax.ContentHandler;
public abstract class MetadataParser extends XMLParser implements XMLConstants {
static final ILicense[] NO_LICENSES = new ILicense[0];
- static final String ATTR_TYPE_LIST_HEAD = "List<"; //$NON-NLS-1$
- static final String ATTR_TYPE_STRING = String.class.getSimpleName();
- static final String ATTR_TYPE_INTEGER = Integer.class.getSimpleName();
- static final String ATTR_TYPE_LONG = Long.class.getSimpleName();
- static final String ATTR_TYPE_FLOAT = Float.class.getSimpleName();
- static final String ATTR_TYPE_DOUBLE = Double.class.getSimpleName();
- static final String ATTR_TYPE_BYTE = Byte.class.getSimpleName();
- static final String ATTR_TYPE_SHORT = Short.class.getSimpleName();
- static final String ATTR_TYPE_CHARACTER = Character.class.getSimpleName();
- static final String ATTR_TYPE_BOOLEAN = Boolean.class.getSimpleName();
- static final String ATTR_TYPE_VERSION = Version.class.getSimpleName();
-
public MetadataParser(BundleContext context, String bundleId) {
super(context, bundleId);
}
@@ -322,7 +313,7 @@ public abstract class MetadataParser extends XMLParser implements XMLConstants {
IProvidedCapability[] providedCapabilities = (providedCapabilitiesHandler == null ? new IProvidedCapability[0] : providedCapabilitiesHandler.getProvidedCapabilities());
currentUnit.setCapabilities(providedCapabilities);
- IRequirement[] requiredCapabilities = (requiredCapabilitiesHandler == null ? new IRequirement[0] : requiredCapabilitiesHandler.getRequiredCapabilities());
+ IRequirement[] requiredCapabilities = (requiredCapabilitiesHandler == null ? new IRequirement[0] : requiredCapabilitiesHandler.getRequirements());
currentUnit.setRequirements(requiredCapabilities);
IRequirement[] metaRequiredCapabilities = (metaRequiredCapabilitiesHandler == null ? new IRequirement[0] : metaRequiredCapabilitiesHandler.getMetaRequiredCapabilities());
currentUnit.setMetaRequirements(metaRequiredCapabilities);
@@ -389,7 +380,7 @@ public abstract class MetadataParser extends XMLParser implements XMLConstants {
@Override
protected void finished() {
if (children != null) {
- scopes.add(children.getRequiredCapabilities());
+ scopes.add(children.getRequirements());
}
}
}
@@ -517,7 +508,7 @@ public abstract class MetadataParser extends XMLParser implements XMLConstants {
private String namespace;
private String name;
private Version version;
- private ProvidedCapabilityAttributesHandler attributesHandler;
+ private ProvidedCapabilityPropertiesHandler propertiesHandler;
private List<IProvidedCapability> capabilities;
@@ -534,63 +525,68 @@ public abstract class MetadataParser extends XMLParser implements XMLConstants {
@Override
public void startElement(String elem, Attributes attributes) {
- if (elem.equals(CAPABILITY_ATTRIBUTES_ELEMENT)) {
- this.attributesHandler = new ProvidedCapabilityAttributesHandler(this, attributes);
- } else {
- invalidElement(elem, attributes);
+ switch (elem) {
+ case PROPERTIES_ELEMENT :
+ this.propertiesHandler = new ProvidedCapabilityPropertiesHandler(this, attributes);
+ break;
+ default :
+ invalidElement(elem, attributes);
+ break;
}
}
@Override
protected void finished() {
- Map<String, Object> capAttrs = (attributesHandler != null)
- ? attributesHandler.getAttributes()
+ Map<String, Object> properties = (propertiesHandler != null)
+ ? propertiesHandler.getProperties()
: new HashMap<>();
- capAttrs.put(namespace, name);
- capAttrs.put(ProvidedCapability.ATTRIBUTE_VERSION, version);
- IProvidedCapability cap = MetadataFactory.createProvidedCapability(namespace, capAttrs);
+ properties.put(namespace, name);
+ properties.put(IProvidedCapability.PROPERTY_VERSION, version);
+ IProvidedCapability cap = MetadataFactory.createProvidedCapability(namespace, properties);
capabilities.add(cap);
}
}
- protected class ProvidedCapabilityAttributesHandler extends AbstractMetadataHandler {
- private Map<String, Object> capAttributes;
+ protected class ProvidedCapabilityPropertiesHandler extends AbstractMetadataHandler {
+ private Map<String, Object> properties;
- public ProvidedCapabilityAttributesHandler(AbstractHandler parentHandler, Attributes attributes) {
- super(parentHandler, CAPABILITY_ATTRIBUTES_ELEMENT);
- // TODO add getOptionalSize(attributes, 4)
- this.capAttributes = new HashMap<>();
+ public ProvidedCapabilityPropertiesHandler(AbstractHandler parentHandler, Attributes attributes) {
+ super(parentHandler, PROPERTIES_ELEMENT);
+ this.properties = new HashMap<>(getOptionalSize(attributes, 2));
}
- public Map<String, Object> getAttributes() {
- return capAttributes;
+ public Map<String, Object> getProperties() {
+ return properties;
}
@Override
- public void startElement(String name, Attributes attributes) {
- if (name.equals(CAPABILITY_ATTRIBUTE_ELEMENT)) {
- new ProvidedCapabilityAttributeHandler(this, attributes, capAttributes);
- } else {
- invalidElement(name, attributes);
+ public void startElement(String elem, Attributes attributes) {
+ switch (elem) {
+ case PROPERTY_ELEMENT :
+ new ProvidedCapabilityPropertyHandler(this, attributes, properties);
+ break;
+ default :
+ invalidElement(elem, attributes);
+ break;
}
}
}
- protected class ProvidedCapabilityAttributeHandler extends AbstractMetadataHandler {
- public ProvidedCapabilityAttributeHandler(AbstractHandler parentHandler, Attributes attributes, Map<String, Object> capAttributes) {
- super(parentHandler, CAPABILITY_ATTRIBUTE_ELEMENT);
+ protected class ProvidedCapabilityPropertyHandler extends AbstractMetadataHandler {
+ public ProvidedCapabilityPropertyHandler(AbstractHandler parentHandler, Attributes attributes, Map<String, Object> properties) {
+ super(parentHandler, PROPERTY_ELEMENT);
- String[] values = parseRequiredAttributes(attributes, CAPABILITY_ATTRIBUTE_REQUIRED_ATTRIBUTES);
+ String[] values = parseAttributes(attributes, PROPERTY_ATTRIBUTES, PROPERTY_OPTIONAL_ATTRIBUTES);
String name = values[0];
String value = values[1];
- String type = values[2];
+ String type = values[2] == null ? PROPERTY_TYPE_STRING : values[2];
- if (type.startsWith(ATTR_TYPE_LIST_HEAD)) {
- capAttributes.put(name, parseList(type, value));
+ if (type.startsWith(PROPERTY_TYPE_LIST)) {
+ properties.put(name, parseList(type, value));
} else {
- capAttributes.put(name, parseScalar(type, value));
+ properties.put(name, parseScalar(type, value));
}
}
@@ -600,49 +596,53 @@ public abstract class MetadataParser extends XMLParser implements XMLConstants {
}
private List<Object> parseList(String type, String value) {
- String elType = type.substring(ATTR_TYPE_LIST_HEAD.length(), type.length() - 1);
-
- List<Object> res = new ArrayList<>();
- for (String el : value.split("\\s*,\\s*")) { //$NON-NLS-1$
- res.add(parseScalar(elType, el));
+ final String elType;
+ if (type.length() > PROPERTY_TYPE_LIST.length()) {
+ // Strip the leading "List<" and trailing ">"
+ elType = type.substring(PROPERTY_TYPE_LIST.length() + 1, type.length() - 1);
+ } else {
+ elType = PROPERTY_TYPE_STRING;
}
- return res;
+ return Arrays.stream(value.split("\\s*,\\s*")) //$NON-NLS-1$
+ .map(val -> parseScalar(elType, val))
+ .collect(toList());
}
private Object parseScalar(String type, String value) {
- if (ATTR_TYPE_STRING.equals(type)) {
+ if (PROPERTY_TYPE_STRING.equals(type)) {
return value;
}
- if (ATTR_TYPE_INTEGER.equals(type)) {
+ if (PROPERTY_TYPE_INTEGER.equals(type)) {
return Integer.parseInt(value);
}
- if (ATTR_TYPE_LONG.equals(type)) {
+ if (PROPERTY_TYPE_LONG.equals(type)) {
return Long.parseLong(value);
}
- if (ATTR_TYPE_FLOAT.equals(type)) {
+ if (PROPERTY_TYPE_FLOAT.equals(type)) {
return Float.parseFloat(value);
}
- if (ATTR_TYPE_DOUBLE.equals(type)) {
+ if (PROPERTY_TYPE_DOUBLE.equals(type)) {
return Double.parseDouble(value);
}
- if (ATTR_TYPE_BYTE.equals(type)) {
+ if (PROPERTY_TYPE_BYTE.equals(type)) {
return Byte.parseByte(value);
}
- if (ATTR_TYPE_SHORT.equals(type)) {
+ if (PROPERTY_TYPE_SHORT.equals(type)) {
return Short.parseShort(value);
}
- if (ATTR_TYPE_CHARACTER.equals(type)) {
+ if (PROPERTY_TYPE_CHARACTER.equals(type)) {
return value.charAt(0);
}
- if (ATTR_TYPE_BOOLEAN.equals(type)) {
+ if (PROPERTY_TYPE_BOOLEAN.equals(type)) {
return Boolean.parseBoolean(value);
}
- if (ATTR_TYPE_VERSION.equals(type)) {
+ if (PROPERTY_TYPE_VERSION.equals(type)) {
return Version.create(value);
}
- // TODO Throw what?
- return value.toString();
+
+ // String is the default
+ return value;
}
}
@@ -691,23 +691,29 @@ public abstract class MetadataParser extends XMLParser implements XMLConstants {
}
protected class RequirementsHandler extends AbstractMetadataHandler {
- private List<IRequirement> requiredCapabilities;
+ private List<IRequirement> requirements;
public RequirementsHandler(AbstractHandler parentHandler, Attributes attributes) {
super(parentHandler, REQUIREMENTS_ELEMENT);
- requiredCapabilities = new ArrayList<>(getOptionalSize(attributes, 4));
+ requirements = new ArrayList<>(getOptionalSize(attributes, 4));
}
- public IRequirement[] getRequiredCapabilities() {
- return requiredCapabilities.toArray(new IRequirement[requiredCapabilities.size()]);
+ public IRequirement[] getRequirements() {
+ return requirements.toArray(new IRequirement[requirements.size()]);
}
@Override
public void startElement(String name, Attributes attributes) {
- if (name.equals(REQUIREMENT_ELEMENT)) {
- new RequirementHandler(this, attributes, requiredCapabilities);
- } else {
- invalidElement(name, attributes);
+ switch (name) {
+ case REQUIREMENT_ELEMENT :
+ new RequirementHandler(this, attributes, requirements);
+ break;
+ case REQUIREMENT_PROPERTIES_ELEMENT :
+ new RequirementPropertiesHandler(this, attributes, requirements);
+ break;
+ default :
+ invalidElement(name, attributes);
+ break;
}
}
}
@@ -734,31 +740,34 @@ public abstract class MetadataParser extends XMLParser implements XMLConstants {
public RequirementHandler(AbstractHandler parentHandler, Attributes attributes, List<IRequirement> capabilities) {
super(parentHandler, REQUIREMENT_ELEMENT);
this.capabilities = capabilities;
+
+ // Version range requirement
if (attributes.getIndex(NAMESPACE_ATTRIBUTE) >= 0) {
- String[] values = parseAttributes(attributes, REQIURED_CAPABILITY_ATTRIBUTES, OPTIONAL_CAPABILITY_ATTRIBUTES);
+ String[] values = parseAttributes(attributes, REQIURED_CAPABILITY_ATTRIBUTES, REQUIRED_CAPABILITY_OPTIONAL_ATTRIBUTES);
namespace = values[0];
name = values[1];
range = checkVersionRange(REQUIREMENT_ELEMENT, VERSION_RANGE_ATTRIBUTE, values[2]);
- boolean isOptional = checkBoolean(REQUIREMENT_ELEMENT, CAPABILITY_OPTIONAL_ATTRIBUTE, values[3], false).booleanValue();
+ boolean isOptional = checkBoolean(REQUIREMENT_ELEMENT, REQUIRED_CAPABILITY_OPTIONAL_ATTRIBUTE, values[3], false).booleanValue();
min = isOptional ? 0 : 1;
- boolean isMultiple = checkBoolean(REQUIREMENT_ELEMENT, CAPABILITY_MULTIPLE_ATTRIBUTE, values[4], false).booleanValue();
+ boolean isMultiple = checkBoolean(REQUIREMENT_ELEMENT, REQUIRED_CAPABILITY_MULTIPLE_ATTRIBUTE, values[4], false).booleanValue();
max = isMultiple ? Integer.MAX_VALUE : 1;
- greedy = checkBoolean(REQUIREMENT_ELEMENT, CAPABILITY_GREED_ATTRIBUTE, values[5], true).booleanValue();
- } else {
- // Expression based requirement
- String[] values = parseAttributes(attributes, REQIUREMENT_ATTRIBUTES, OPTIONAL_REQUIREMENT_ATTRIBUTES);
+ greedy = checkBoolean(REQUIREMENT_ELEMENT, REQUIREMENT_GREED_ATTRIBUTE, values[5], true).booleanValue();
+ }
+ // IU match expression requirement
+ else {
+ String[] values = parseAttributes(attributes, REQUIRED_IU_MATCH_ATTRIBUTES, REQUIRED_IU_MATCH_OPTIONAL_ATTRIBUTES);
match = values[0];
matchParams = values[1];
min = values[2] == null ? 1 : checkInteger(REQUIREMENT_ELEMENT, MIN_ATTRIBUTE, values[2]);
max = values[3] == null ? 1 : checkInteger(REQUIREMENT_ELEMENT, MAX_ATTRIBUTE, values[3]);
- greedy = checkBoolean(REQUIREMENT_ELEMENT, CAPABILITY_GREED_ATTRIBUTE, values[4], true).booleanValue();
+ greedy = checkBoolean(REQUIREMENT_ELEMENT, REQUIREMENT_GREED_ATTRIBUTE, values[4], true).booleanValue();
}
}
@Override
public void startElement(String elem, Attributes attributes) {
- if (elem.equals(CAPABILITY_FILTER_ELEMENT)) {
- filterHandler = new TextHandler(this, CAPABILITY_FILTER_ELEMENT, attributes);
+ if (elem.equals(REQUIREMENT_FILTER_ELEMENT)) {
+ filterHandler = new TextHandler(this, REQUIREMENT_FILTER_ELEMENT, attributes);
} else if (elem.equals(REQUIREMENT_DESCRIPTION_ELEMENT)) {
descriptionHandler = new TextHandler(this, REQUIREMENT_DESCRIPTION_ELEMENT, attributes);
} else {
@@ -805,6 +814,83 @@ public abstract class MetadataParser extends XMLParser implements XMLConstants {
}
}
+ protected class RequirementPropertiesHandler extends AbstractHandler {
+ private List<IRequirement> requirements;
+
+ private String namespace;
+ private String match;
+ private int min;
+ private int max;
+ private boolean greedy;
+
+ private TextHandler filterHandler;
+ private TextHandler descriptionHandler;
+
+ public RequirementPropertiesHandler(AbstractHandler parentHandler, Attributes attributes, List<IRequirement> requirements) {
+ super(parentHandler, REQUIREMENT_PROPERTIES_ELEMENT);
+ this.requirements = requirements;
+
+ String[] values = parseAttributes(attributes, REQIURED_PROPERTIES_MATCH_ATTRIBUTES, REQIURED_PROPERTIES_MATCH_OPTIONAL_ATTRIBUTES);
+ namespace = values[0];
+ match = values[1];
+ min = (values[2] == null) ? 1 : checkInteger(REQUIREMENT_PROPERTIES_ELEMENT, MIN_ATTRIBUTE, values[2]);
+ max = (values[3] == null) ? 1 : checkInteger(REQUIREMENT_PROPERTIES_ELEMENT, MAX_ATTRIBUTE, values[3]);
+ greedy = checkBoolean(REQUIREMENT_PROPERTIES_ELEMENT, REQUIREMENT_GREED_ATTRIBUTE, values[4], true).booleanValue();
+ }
+
+ @Override
+ public void startElement(String elem, Attributes attributes) {
+ switch (elem) {
+ case REQUIREMENT_FILTER_ELEMENT :
+ filterHandler = new TextHandler(this, REQUIREMENT_FILTER_ELEMENT, attributes);
+ break;
+ case REQUIREMENT_DESCRIPTION_ELEMENT :
+ descriptionHandler = new TextHandler(this, REQUIREMENT_DESCRIPTION_ELEMENT, attributes);
+ break;
+ default :
+ invalidElement(elem, attributes);
+ break;
+ }
+ }
+
+ @Override
+ protected void finished() {
+ if (!isValidXML()) {
+ return;
+ }
+
+ IMatchExpression<IInstallableUnit> filter = null;
+ if (filterHandler != null) {
+ try {
+ filter = InstallableUnit.parseFilter(filterHandler.getText());
+ } catch (ExpressionParseException e) {
+ if (removeWhiteSpace(filterHandler.getText()).equals("(&(|)(|)(|))")) {//$NON-NLS-1$
+ // We could log this I guess
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ String description = (descriptionHandler != null) ? descriptionHandler.getText() : null;
+
+ IFilterExpression attrMatch = ExpressionUtil.parseLDAP(match);
+ IRequirement requirement = MetadataFactory.createRequirement(namespace, attrMatch, filter, min, max, greedy, description);
+ requirements.add(requirement);
+ }
+
+ private String removeWhiteSpace(String s) {
+ if (s == null)
+ return ""; //$NON-NLS-1$
+ StringBuffer builder = new StringBuffer();
+ for (int i = 0; i < s.length(); i++) {
+ if (s.charAt(i) != ' ')
+ builder.append(s.charAt(i));
+ }
+ return builder.toString();
+ }
+ }
+
protected class ArtifactsHandler extends AbstractHandler {
private List<IArtifactKey> artifacts;
diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/MetadataWriter.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/MetadataWriter.java
index 2b7686e35..f88d52bdd 100644
--- a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/MetadataWriter.java
+++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/MetadataWriter.java
@@ -14,11 +14,10 @@ package org.eclipse.equinox.internal.p2.metadata.repository.io;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.util.*;
-import java.util.Map.Entry;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
-import org.eclipse.equinox.internal.p2.metadata.ProvidedCapability;
import org.eclipse.equinox.internal.p2.metadata.RequiredCapability;
+import org.eclipse.equinox.internal.p2.metadata.RequiredPropertiesMatch;
import org.eclipse.equinox.internal.p2.metadata.repository.Activator;
import org.eclipse.equinox.internal.p2.persistence.XMLWriter;
import org.eclipse.equinox.p2.metadata.*;
@@ -96,23 +95,23 @@ public class MetadataWriter extends XMLWriter implements XMLConstants {
private boolean hasOnlySimpleRequirements(IInstallableUnit iu) {
for (IRequirement r : iu.getRequirements())
- if (r.getMax() == 0 || !RequiredCapability.isSimpleRequirement(r.getMatches()))
+ if (r.getMax() == 0 || !RequiredCapability.isVersionRangeRequirement(r.getMatches()))
return false;
if (iu.getUpdateDescriptor() != null) {
for (IMatchExpression<IInstallableUnit> m : iu.getUpdateDescriptor().getIUsBeingUpdated()) {
- if (!RequiredCapability.isSimpleRequirement(m))
+ if (!RequiredCapability.isVersionRangeRequirement(m))
return false;
}
}
for (IRequirement r : iu.getMetaRequirements())
- if (r.getMax() == 0 || !RequiredCapability.isSimpleRequirement(r.getMatches()))
+ if (r.getMax() == 0 || !RequiredCapability.isVersionRangeRequirement(r.getMatches()))
return false;
if (iu instanceof IInstallableUnitFragment) {
for (IRequirement r : ((IInstallableUnitFragment) iu).getHost())
- if (!RequiredCapability.isSimpleRequirement(r.getMatches()))
+ if (!RequiredCapability.isVersionRangeRequirement(r.getMatches()))
return false;
}
@@ -120,11 +119,11 @@ public class MetadataWriter extends XMLWriter implements XMLConstants {
IInstallableUnitPatch iuPatch = (IInstallableUnitPatch) iu;
for (IRequirement[] rArr : iuPatch.getApplicabilityScope())
for (IRequirement r : rArr)
- if (!RequiredCapability.isSimpleRequirement(r.getMatches()))
+ if (!RequiredCapability.isVersionRangeRequirement(r.getMatches()))
return false;
IRequirement lifeCycle = iuPatch.getLifeCycle();
- if (lifeCycle != null && !RequiredCapability.isSimpleRequirement(lifeCycle.getMatches()))
+ if (lifeCycle != null && !RequiredCapability.isVersionRangeRequirement(lifeCycle.getMatches()))
return false;
}
return true;
@@ -167,50 +166,12 @@ public class MetadataWriter extends XMLWriter implements XMLConstants {
attribute(NAME_ATTRIBUTE, capability.getName());
attribute(VERSION_ATTRIBUTE, capability.getVersion());
- Map<String, Object> attrs = new HashMap<>(capability.getAttributes());
- attrs.remove(capability.getNamespace());
- attrs.remove(ProvidedCapability.ATTRIBUTE_VERSION);
+ Map<String, Object> props = new HashMap<>(capability.getProperties());
+ props.remove(capability.getNamespace());
+ props.remove(IProvidedCapability.PROPERTY_VERSION);
- if (!attrs.isEmpty()) {
- start(CAPABILITY_ATTRIBUTES_ELEMENT);
- attribute(COLLECTION_SIZE_ATTRIBUTE, attrs.size());
-
- for (Entry<String, Object> attr : attrs.entrySet()) {
- start(CAPABILITY_ATTRIBUTE_ELEMENT);
-
- String name = attr.getKey();
- Object val = attr.getValue();
- String type;
-
- if (Collection.class.isAssignableFrom(val.getClass())) {
- Collection<?> coll = (Collection<?>) val;
-
- String elType = coll.iterator().next().getClass().getSimpleName();
- type = String.format("List<%s>", elType); //$NON-NLS-1$
-
- StringBuilder valBuff = new StringBuilder();
- for (Iterator<?> iter = coll.iterator(); iter.hasNext();) {
- String el = iter.next().toString();
-
- valBuff.append(el);
- if (iter.hasNext()) {
- valBuff.append(","); //$NON-NLS-1$
- }
- }
-
- val = valBuff.toString();
- } else {
- type = val.getClass().getSimpleName();
- val = val.toString();
- }
-
- attribute(CAPABILITY_ATTRIBUTE_NAME_ATTRIBUTE, name);
- attribute(CAPABILITY_ATTRIBUTE_TYPE_ATTRIBUTE, type);
- attribute(CAPABILITY_ATTRIBUTE_VALUE_ATTRIBUTE, val);
-
- end(CAPABILITY_ATTRIBUTE_ELEMENT);
- }
- end(CAPABILITY_ATTRIBUTES_ELEMENT);
+ if (!props.isEmpty()) {
+ writeProperties(props);
}
end(PROVIDED_CAPABILITY_ELEMENT);
@@ -246,7 +207,7 @@ public class MetadataWriter extends XMLWriter implements XMLConstants {
throw new IllegalStateException();
IMatchExpression<IInstallableUnit> singleUD = descriptor.getIUsBeingUpdated().iterator().next();
start(UPDATE_DESCRIPTOR_ELEMENT);
- if (RequiredCapability.isSimpleRequirement(singleUD)) {
+ if (RequiredCapability.isVersionRangeRequirement(singleUD)) {
attribute(ID_ATTRIBUTE, RequiredCapability.extractName(singleUD));
attribute(VERSION_RANGE_ATTRIBUTE, RequiredCapability.extractRange(singleUD));
} else {
@@ -291,27 +252,59 @@ public class MetadataWriter extends XMLWriter implements XMLConstants {
}
protected void writeRequirement(IRequirement requirement) {
- start(REQUIREMENT_ELEMENT);
IMatchExpression<IInstallableUnit> match = requirement.getMatches();
- if (requirement.getMax() > 0 && RequiredCapability.isSimpleRequirement(match)) {
+
+ // A (namespace, name, version-range) type of requirement
+ if (requirement.getMax() > 0 && RequiredCapability.isVersionRangeRequirement(match)) {
+ start(REQUIREMENT_ELEMENT);
+
attribute(NAMESPACE_ATTRIBUTE, RequiredCapability.extractNamespace(match));
attribute(NAME_ATTRIBUTE, RequiredCapability.extractName(match));
attribute(VERSION_RANGE_ATTRIBUTE, RequiredCapability.extractRange(match));
- attribute(CAPABILITY_OPTIONAL_ATTRIBUTE, requirement.getMin() == 0, false);
- attribute(CAPABILITY_MULTIPLE_ATTRIBUTE, requirement.getMax() > 1, false);
- } else {
+ attribute(REQUIRED_CAPABILITY_OPTIONAL_ATTRIBUTE, requirement.getMin() == 0, false);
+ attribute(REQUIRED_CAPABILITY_MULTIPLE_ATTRIBUTE, requirement.getMax() > 1, false);
+ }
+ // A (namespace, attributes-match) type of requirement
+ else if (RequiredPropertiesMatch.isPropertiesMatchRequirement(match)) {
+ start(REQUIREMENT_PROPERTIES_ELEMENT);
+
+ attribute(NAMESPACE_ATTRIBUTE, RequiredPropertiesMatch.extractNamespace(match));
+ attribute(MATCH_ATTRIBUTE, RequiredPropertiesMatch.extractPropertiesMatch(match));
+
+ if (requirement.getMin() != 1) {
+ attribute(MIN_ATTRIBUTE, requirement.getMin());
+ }
+
+ if (requirement.getMax() != 1) {
+ attribute(MAX_ATTRIBUTE, requirement.getMax());
+ }
+ }
+ // A general match expression type of requirement
+ else {
+ start(REQUIREMENT_ELEMENT);
+
writeMatchExpression(match);
- if (requirement.getMin() != 1)
+
+ if (requirement.getMin() != 1) {
attribute(MIN_ATTRIBUTE, requirement.getMin());
- if (requirement.getMax() != 1)
+ }
+
+ if (requirement.getMax() != 1) {
attribute(MAX_ATTRIBUTE, requirement.getMax());
+ }
+ }
+
+ attribute(REQUIREMENT_GREED_ATTRIBUTE, requirement.isGreedy(), true);
+
+ if (requirement.getFilter() != null) {
+ writeTrimmedCdata(REQUIREMENT_FILTER_ELEMENT, requirement.getFilter().getParameters()[0].toString());
}
- attribute(CAPABILITY_GREED_ATTRIBUTE, requirement.isGreedy(), true);
- if (requirement.getFilter() != null)
- writeTrimmedCdata(CAPABILITY_FILTER_ELEMENT, requirement.getFilter().getParameters()[0].toString());
- if (requirement.getDescription() != null)
+
+ if (requirement.getDescription() != null) {
writeTrimmedCdata(REQUIREMENT_DESCRIPTION_ELEMENT, requirement.getDescription());
- end(REQUIREMENT_ELEMENT);
+ }
+
+ end();
}
private void writeMatchExpression(IMatchExpression<IInstallableUnit> match) {
diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/XMLConstants.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/XMLConstants.java
index 44db99925..621356e4a 100644
--- a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/XMLConstants.java
+++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/p2/metadata/repository/io/XMLConstants.java
@@ -39,9 +39,7 @@ public interface XMLConstants extends org.eclipse.equinox.internal.p2.persistenc
public static final String REQUIREMENTS_ELEMENT = "requires"; //$NON-NLS-1$
public static final String HOST_REQUIREMENTS_ELEMENT = "hostRequirements"; //$NON-NLS-1$
public static final String META_REQUIREMENTS_ELEMENT = "metaRequirements"; //$NON-NLS-1$
- public static final String REQUIREMENT_ELEMENT = "required"; //$NON-NLS-1$
public static final String PROVIDED_CAPABILITIES_ELEMENT = "provides"; //$NON-NLS-1$
- public static final String PROVIDED_CAPABILITY_ELEMENT = "provided"; //$NON-NLS-1$
public static final String[] REQUIRED_PROVIDED_CAPABILITY_ATTRIBUTES = new String[] {NAMESPACE_ATTRIBUTE, NAME_ATTRIBUTE, VERSION_ATTRIBUTE};
public static final String TOUCHPOINT_TYPE_ELEMENT = "touchpoint"; //$NON-NLS-1$
public static final String TOUCHPOINT_DATA_ELEMENT = "touchpointData"; //$NON-NLS-1$
@@ -63,26 +61,26 @@ public interface XMLConstants extends org.eclipse.equinox.internal.p2.persistenc
public static final String[] OPTIONAL_IU_ATTRIBUTES = new String[] {SINGLETON_ATTRIBUTE};
public static final String GENERATION_ATTRIBUTE = "generation"; //$NON-NLS-1$
+ // Constants for the provided capability element
+ public static final String PROVIDED_CAPABILITY_ELEMENT = "provided"; //$NON-NLS-1$
+
// Constants for sub-elements of a required capability element
- public static final String CAPABILITY_FILTER_ELEMENT = "filter"; //$NON-NLS-1$
+ public static final String REQUIREMENT_ELEMENT = "required"; //$NON-NLS-1$
+ public static final String REQUIREMENT_PROPERTIES_ELEMENT = "requiredProperties"; //$NON-NLS-1$
+ public static final String REQUIREMENT_FILTER_ELEMENT = "filter"; //$NON-NLS-1$
public static final String REQUIREMENT_DESCRIPTION_ELEMENT = "description"; //$NON-NLS-1$
+ public static final String REQUIREMENT_GREED_ATTRIBUTE = "greedy"; //$NON-NLS-1$
- // Constants for attributes of a required capability element
- public static final String CAPABILITY_OPTIONAL_ATTRIBUTE = "optional"; //$NON-NLS-1$
- public static final String CAPABILITY_MULTIPLE_ATTRIBUTE = "multiple"; //$NON-NLS-1$
- public static final String CAPABILITY_GREED_ATTRIBUTE = "greedy"; //$NON-NLS-1$
+ public static final String REQUIRED_CAPABILITY_OPTIONAL_ATTRIBUTE = "optional"; //$NON-NLS-1$
+ public static final String REQUIRED_CAPABILITY_MULTIPLE_ATTRIBUTE = "multiple"; //$NON-NLS-1$
+ public static final String[] REQIURED_CAPABILITY_ATTRIBUTES = new String[] {NAMESPACE_ATTRIBUTE, NAME_ATTRIBUTE, VERSION_RANGE_ATTRIBUTE};
+ public static final String[] REQUIRED_CAPABILITY_OPTIONAL_ATTRIBUTES = new String[] {REQUIRED_CAPABILITY_OPTIONAL_ATTRIBUTE, REQUIRED_CAPABILITY_MULTIPLE_ATTRIBUTE, REQUIREMENT_GREED_ATTRIBUTE};
- public static final String CAPABILITY_ATTRIBUTES_ELEMENT = "attributes"; //$NON-NLS-1$
- public static final String CAPABILITY_ATTRIBUTE_ELEMENT = "attribute"; //$NON-NLS-1$
- public static final String CAPABILITY_ATTRIBUTE_NAME_ATTRIBUTE = "name"; //$NON-NLS-1$
- public static final String CAPABILITY_ATTRIBUTE_TYPE_ATTRIBUTE = "type"; //$NON-NLS-1$
- public static final String CAPABILITY_ATTRIBUTE_VALUE_ATTRIBUTE = "value"; //$NON-NLS-1$
- public static final String[] CAPABILITY_ATTRIBUTE_REQUIRED_ATTRIBUTES = new String[] {CAPABILITY_ATTRIBUTE_NAME_ATTRIBUTE, CAPABILITY_ATTRIBUTE_VALUE_ATTRIBUTE, CAPABILITY_ATTRIBUTE_TYPE_ATTRIBUTE};
+ public static final String[] REQIURED_PROPERTIES_MATCH_ATTRIBUTES = new String[] {NAMESPACE_ATTRIBUTE, MATCH_ATTRIBUTE};
+ public static final String[] REQIURED_PROPERTIES_MATCH_OPTIONAL_ATTRIBUTES = new String[] {MIN_ATTRIBUTE, MAX_ATTRIBUTE, REQUIREMENT_GREED_ATTRIBUTE};
- public static final String[] REQIURED_CAPABILITY_ATTRIBUTES = new String[] {NAMESPACE_ATTRIBUTE, NAME_ATTRIBUTE, VERSION_RANGE_ATTRIBUTE};
- public static final String[] REQIUREMENT_ATTRIBUTES = new String[] {MATCH_ATTRIBUTE};
- public static final String[] OPTIONAL_CAPABILITY_ATTRIBUTES = new String[] {CAPABILITY_OPTIONAL_ATTRIBUTE, CAPABILITY_MULTIPLE_ATTRIBUTE, CAPABILITY_GREED_ATTRIBUTE};
- public static final String[] OPTIONAL_REQUIREMENT_ATTRIBUTES = new String[] {MATCH_PARAMETERS_ATTRIBUTE, MIN_ATTRIBUTE, MAX_ATTRIBUTE, CAPABILITY_GREED_ATTRIBUTE};
+ public static final String[] REQUIRED_IU_MATCH_ATTRIBUTES = new String[] {MATCH_ATTRIBUTE};
+ public static final String[] REQUIRED_IU_MATCH_OPTIONAL_ATTRIBUTES = new String[] {MATCH_PARAMETERS_ATTRIBUTE, MIN_ATTRIBUTE, MAX_ATTRIBUTE, REQUIREMENT_GREED_ATTRIBUTE};
// Constants for attributes of an artifact key element
public static final String ARTIFACT_KEY_CLASSIFIER_ATTRIBUTE = "classifier"; //$NON-NLS-1$
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ProvidedCapability.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ProvidedCapability.java
index 13eb67642..31297abf8 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ProvidedCapability.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/ProvidedCapability.java
@@ -9,10 +9,14 @@
* IBM Corporation - initial API and implementation
* EclipseSource - ongoing development
* SAP - ongoing development
+ * Todor Boev
*******************************************************************************/
package org.eclipse.equinox.internal.p2.metadata;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.eclipse.core.runtime.Assert;
@@ -31,44 +35,65 @@ public class ProvidedCapability implements IProvidedCapability, IMemberProvider
public static final String MEMBER_NAME = "name"; //$NON-NLS-1$
/** Used for fast access from P2 queries to the {@link #getVersion} method */
public static final String MEMBER_VERSION = "version"; //$NON-NLS-1$
- /** Used for fast access from P2 queries to the {@link #getAttributes} method */
- public static final String MEMBER_ATTRIBUTES = "attributes"; //$NON-NLS-1$
-
- // TODO Move this to IProvidedCapability?
- // The "version" attribute is part of the public contract of getVersion() and getAttributes()
- public static final String ATTRIBUTE_VERSION = "version"; //$NON-NLS-1$
+ /** Used for fast access from P2 queries to the {@link #getProperties} method */
+ public static final String MEMBER_PROPERTIES = "properties"; //$NON-NLS-1$
private final String namespace;
- private final Map<String, Object> attributes;
+ private final Map<String, Object> properties;
- public ProvidedCapability(String namespace, Map<String, Object> attrs) {
+ public ProvidedCapability(String namespace, Map<String, Object> props) {
Assert.isNotNull(namespace, NLS.bind(Messages.provided_capability_namespace_not_defined, null));
this.namespace = namespace;
- Assert.isNotNull(attrs);
- Assert.isTrue(!attrs.isEmpty());
+ Assert.isNotNull(props);
+ Assert.isTrue(!props.isEmpty());
+
+ assertValidPropertyTypes(props);
- this.attributes = new HashMap<>(attrs);
+ Map<String, Object> resolvedProps = new HashMap<>(props);
// Verify the name
- Assert.isTrue(attributes.containsKey(namespace) && (attributes.get(namespace) instanceof String), NLS.bind(Messages.provided_capability_name_not_defined, namespace));
+ Assert.isTrue(resolvedProps.containsKey(namespace) && (resolvedProps.get(namespace) instanceof String), NLS.bind(Messages.provided_capability_name_not_defined, namespace));
// Verify the version
- Object version = attributes.get(ATTRIBUTE_VERSION);
+ Object version = resolvedProps.get(PROPERTY_VERSION);
if (version != null) {
- Assert.isTrue(attributes.get(ATTRIBUTE_VERSION) instanceof Version);
+ Assert.isTrue(props.get(PROPERTY_VERSION) instanceof Version);
} else {
- attributes.put(ATTRIBUTE_VERSION, Version.emptyVersion);
+ resolvedProps.put(PROPERTY_VERSION, Version.emptyVersion);
}
+
+ this.properties = Collections.unmodifiableMap(props);
}
public ProvidedCapability(String namespace, String name, Version version) {
Assert.isNotNull(namespace, NLS.bind(Messages.provided_capability_namespace_not_defined, null));
Assert.isNotNull(name, NLS.bind(Messages.provided_capability_name_not_defined, namespace));
this.namespace = namespace;
- this.attributes = new HashMap<>();
- attributes.put(namespace, name);
- attributes.put(ATTRIBUTE_VERSION, version == null ? Version.emptyVersion : version);
+ this.properties = new HashMap<>();
+ properties.put(namespace, name);
+ properties.put(PROPERTY_VERSION, version == null ? Version.emptyVersion : version);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder str = new StringBuilder();
+ str.append(namespace);
+
+ for (Entry<String, Object> attr : properties.entrySet()) {
+ String key = attr.getKey();
+ Object val = attr.getValue();
+ String type = val.getClass().getSimpleName();
+
+ str.append("; ").append(key).append(":").append(type).append("=").append(val); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ return str.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return namespace.hashCode() * properties.hashCode();
}
@Override
@@ -87,7 +112,7 @@ public class ProvidedCapability implements IProvidedCapability, IMemberProvider
return false;
}
- if (!(attributes.equals(otherCapability.getAttributes()))) {
+ if (!(properties.equals(otherCapability.getProperties()))) {
return false;
}
@@ -101,38 +126,17 @@ public class ProvidedCapability implements IProvidedCapability, IMemberProvider
@Override
public String getName() {
- return (String) attributes.get(namespace);
+ return (String) properties.get(namespace);
}
@Override
public Version getVersion() {
- return (Version) attributes.get(ATTRIBUTE_VERSION);
+ return (Version) properties.get(PROPERTY_VERSION);
}
@Override
- public Map<String, Object> getAttributes() {
- return attributes;
- }
-
- @Override
- public int hashCode() {
- return namespace.hashCode() * attributes.hashCode();
- }
-
- @Override
- public String toString() {
- StringBuilder str = new StringBuilder();
- str.append(namespace);
-
- for (Entry<String, Object> attr : attributes.entrySet()) {
- String key = attr.getKey();
- Object val = attr.getValue();
- String type = val.getClass().getSimpleName();
-
- str.append("; ").append(key).append(":").append(type).append("=").append(val); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
- }
-
- return str.toString();
+ public Map<String, Object> getProperties() {
+ return properties;
}
@Override
@@ -141,13 +145,36 @@ public class ProvidedCapability implements IProvidedCapability, IMemberProvider
case MEMBER_NAMESPACE :
return namespace;
case MEMBER_NAME :
- return attributes.get(namespace);
+ return properties.get(namespace);
case MEMBER_VERSION :
- return attributes.get(ATTRIBUTE_VERSION);
- case MEMBER_ATTRIBUTES :
- return attributes;
+ return properties.get(PROPERTY_VERSION);
+ case MEMBER_PROPERTIES :
+ return properties;
default :
- throw new IllegalArgumentException("No such member: " + memberName); //$NON-NLS-1$
+ throw new IllegalArgumentException(String.format("No such member: %s", memberName)); //$NON-NLS-1$
+ }
+ }
+
+ private void assertValidPropertyTypes(Map<String, Object> props) {
+ props.forEach(this::assertValidValueType);
+ }
+
+ private void assertValidValueType(String key, Object prop) {
+ if (prop instanceof List<?>) {
+ int idx = 0;
+ for (Object scalar : (List<?>) prop) {
+ assertValidScalarType(String.format("%s[%s]", key, idx++), scalar); //$NON-NLS-1$
+ }
+ } else {
+ assertValidScalarType(key, prop);
}
}
+
+ private void assertValidScalarType(String key, Object scalar) {
+ Arrays.asList(Version.class, String.class, Long.class, Integer.class, Short.class, Byte.class, Double.class, Float.class, Boolean.class, Character.class)
+ .stream()
+ .filter(t -> t.isAssignableFrom(scalar.getClass()))
+ .findFirst()
+ .orElseThrow(() -> new IllegalArgumentException(String.format("Invalid type %s of property %s", scalar.getClass(), key))); //$NON-NLS-1$
+ }
}
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredCapability.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredCapability.java
index cd8f8dac8..c08af575d 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredCapability.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredCapability.java
@@ -39,27 +39,14 @@ import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
* @see IInstallableUnit#NAMESPACE_IU_ID
*/
public class RequiredCapability extends Requirement implements IRequiredCapability {
- private static final IExpression simpleMatchExpression;
-
- static {
- IExpressionFactory factory = ExpressionUtil.getFactory();
-
- IExpression xVar = factory.variable("cap"); //$NON-NLS-1$
-
- IExpression name = factory.member(xVar, MEMBER_NAME);
- IExpression nameEqual = factory.equals(name, factory.indexedParameter(0));
-
- IExpression namespace = factory.member(xVar, MEMBER_NAMESPACE);
- IExpression namespaceEqual = factory.equals(namespace, factory.indexedParameter(1));
-
- IExpression version = factory.member(xVar, MEMBER_VERSION);
- IExpression versionInRange = factory.matches(version, factory.indexedParameter(2));
-
- IExpression pvMember = factory.member(factory.thisVariable(), MEMBER_PROVIDED_CAPABILITIES);
-
- // Place nameEqual first to eliminate quickly most non-matching candidates
- simpleMatchExpression = factory.exists(pvMember, factory.lambda(xVar, factory.and(nameEqual, namespaceEqual, versionInRange)));
- }
+ /**
+ * Argument $0 must evaluate to a String
+ * Argument $1 must evaluate to a String
+ * Argument $2 must evaluate to a {@link VersionRange}
+ */
+ private static final IExpression VERSION_RANGE_MATCH = ExpressionUtil.parse(
+ String.format("%s.exists(cap | cap.%s == $0 && cap.%s == $1 && cap.%s ~= $2)", //$NON-NLS-1$
+ MEMBER_PROVIDED_CAPABILITIES, MEMBER_NAME, MEMBER_NAMESPACE, MEMBER_VERSION));
/**
* TODO Remove. This is a private impl class. Users must call the analogous MetadataFactory.createRequirement()
@@ -104,17 +91,11 @@ public class RequiredCapability extends Requirement implements IRequiredCapabili
public String toString() {
StringBuilder result = new StringBuilder();
- // Namespace
result.append(getNamespace());
- result.append(' ');
-
- // Name
+ result.append("; "); //$NON-NLS-1$
result.append(getName());
- result.append(' ');
-
- // Version range
- VersionRange range = getRange();
- result.append(range);
+ result.append(" "); //$NON-NLS-1$
+ result.append(getRange());
return result.toString();
}
@@ -124,7 +105,7 @@ public class RequiredCapability extends Requirement implements IRequiredCapabili
Assert.isNotNull(name);
Object resolvedRange = (range != null) ? range : VersionRange.emptyRange;
IExpressionFactory factory = ExpressionUtil.getFactory();
- return factory.matchExpression(simpleMatchExpression, name, namespace, resolvedRange);
+ return factory.matchExpression(VERSION_RANGE_MATCH, name, namespace, resolvedRange);
}
public static String extractNamespace(IMatchExpression<IInstallableUnit> matchExpression) {
@@ -144,7 +125,7 @@ public class RequiredCapability extends Requirement implements IRequiredCapabili
}
public static boolean isVersionStrict(IMatchExpression<IInstallableUnit> matchExpression) {
- if (!isSimpleRequirement(matchExpression)) {
+ if (!isVersionRangeRequirement(matchExpression)) {
return false;
}
@@ -153,12 +134,12 @@ public class RequiredCapability extends Requirement implements IRequiredCapabili
return range.getMinimum().equals(range.getMaximum());
}
- public static boolean isSimpleRequirement(IMatchExpression<IInstallableUnit> matchExpression) {
- return simpleMatchExpression.equals(ExpressionUtil.getOperand(matchExpression));
+ public static boolean isVersionRangeRequirement(IMatchExpression<IInstallableUnit> matchExpression) {
+ return VERSION_RANGE_MATCH.equals(ExpressionUtil.getOperand(matchExpression));
}
private static void assertValid(IMatchExpression<IInstallableUnit> matchExpression) {
- if (!isSimpleRequirement(matchExpression)) {
+ if (!isVersionRangeRequirement(matchExpression)) {
throw new IllegalArgumentException();
}
}
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredPropertiesMatch.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredPropertiesMatch.java
new file mode 100644
index 000000000..a108fadc0
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredPropertiesMatch.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2017 IBM Corporation 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:
+ * Todor Boev
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.metadata;
+
+import static org.eclipse.equinox.internal.p2.metadata.InstallableUnit.MEMBER_PROVIDED_CAPABILITIES;
+import static org.eclipse.equinox.internal.p2.metadata.ProvidedCapability.MEMBER_NAMESPACE;
+import static org.eclipse.equinox.internal.p2.metadata.ProvidedCapability.MEMBER_PROPERTIES;
+
+import org.eclipse.core.runtime.Assert;
+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.expression.ExpressionUtil;
+import org.eclipse.equinox.p2.metadata.expression.IExpression;
+import org.eclipse.equinox.p2.metadata.expression.IExpressionFactory;
+import org.eclipse.equinox.p2.metadata.expression.IFilterExpression;
+import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
+
+/**
+ * A required capability match represents some external constraint on an {@link IInstallableUnit}.
+ * <p>
+ * This is a flavor of the general {@link IRequirement} that searches for
+ * a capability that has {@link IProvidedCapability#getProperties() properties} that match a given expression.
+ * I.e. this is much more limited that an arbitrary match expression executed over all metadata of the IU.
+ */
+public class RequiredPropertiesMatch extends Requirement {
+ /**
+ * Argument $0 must evaluate to a String
+ * Argument $2 must evaluate to an expression compatible with the match operator "~="
+ */
+ private static final IExpression PROPERTIES_MATCH = ExpressionUtil.parse(
+ String.format("%s.exists(cap | cap.%s == $0 && cap.%s ~= $1)", //$NON-NLS-1$
+ MEMBER_PROVIDED_CAPABILITIES, MEMBER_NAMESPACE, MEMBER_PROPERTIES));
+
+ public RequiredPropertiesMatch(String namespace, IFilterExpression attrFilter, IMatchExpression<IInstallableUnit> envFilter, int min, int max, boolean greedy, String description) {
+ super(createMatchExpressionFromFilter(namespace, attrFilter), envFilter, min, max, greedy, description);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder result = new StringBuilder();
+
+ result.append(extractNamespace(getMatches()));
+ result.append("; "); //$NON-NLS-1$
+ result.append(extractPropertiesMatch(getMatches()));
+
+ return result.toString();
+ }
+
+ public static IMatchExpression<IInstallableUnit> createMatchExpressionFromFilter(String namespace, IFilterExpression attrFilter) {
+ Assert.isNotNull(namespace);
+ Assert.isNotNull(attrFilter);
+ IExpressionFactory factory = ExpressionUtil.getFactory();
+ return factory.matchExpression(PROPERTIES_MATCH, namespace, attrFilter);
+ }
+
+ public static String extractNamespace(IMatchExpression<IInstallableUnit> matchExpression) {
+ assertValid(matchExpression);
+ return (String) matchExpression.getParameters()[0];
+ }
+
+ public static IFilterExpression extractPropertiesMatch(IMatchExpression<IInstallableUnit> matchExpression) {
+ assertValid(matchExpression);
+ return (IFilterExpression) matchExpression.getParameters()[1];
+ }
+
+ public static boolean isPropertiesMatchRequirement(IMatchExpression<IInstallableUnit> matchExpression) {
+ return PROPERTIES_MATCH.equals(ExpressionUtil.getOperand(matchExpression));
+ }
+
+ private static void assertValid(IMatchExpression<IInstallableUnit> matchExpression) {
+ if (!isPropertiesMatchRequirement(matchExpression)) {
+ throw new IllegalArgumentException();
+ }
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/Requirement.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/Requirement.java
index 036721c5f..5fe660e82 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/Requirement.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/Requirement.java
@@ -11,7 +11,11 @@
*******************************************************************************/
package org.eclipse.equinox.internal.p2.metadata;
-import org.eclipse.equinox.p2.metadata.*;
+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.VersionRange;
import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
import org.eclipse.equinox.p2.metadata.expression.IMemberProvider;
@@ -66,10 +70,14 @@ public class Requirement implements IRequirement, IMemberProvider {
// Parameters
Object[] params = matchExpression.getParameters();
if (params.length > 0) {
- result.append(' ');
+ result.append(" ("); //$NON-NLS-1$
for (int i = 0; i < params.length; i++) {
- result.append(params[i]).append(' ');
+ if (i > 0) {
+ result.append(", "); //$NON-NLS-1$
+ }
+ result.append(params[i]);
}
+ result.append(')');
}
return result.toString();
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/expression/CoercingComparator.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/expression/CoercingComparator.java
index 6cb8008f7..c6d31687d 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/expression/CoercingComparator.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/expression/CoercingComparator.java
@@ -229,8 +229,6 @@ public abstract class CoercingComparator<T> {
Version coerce(Object v) {
if (v instanceof Version)
return (Version) v;
- if (v instanceof String)
- return Version.create((String) v);
if (v instanceof String) {
try {
return Version.create((String) v);
@@ -333,7 +331,7 @@ public abstract class CoercingComparator<T> {
* @return The coercing comparator
*/
@SuppressWarnings("unchecked")
- public static <V extends Object> CoercingComparator<V> getComparator(V value, Object v2) {
+ public static <V> CoercingComparator<V> getComparator(V value, Object v2) {
Class<V> vClass = (Class<V>) value.getClass();
CoercingComparator<?>[] carr = coercers;
int idx = carr.length;
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/index/CapabilityIndex.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/index/CapabilityIndex.java
index d7b2b3cac..8d89b2d13 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/index/CapabilityIndex.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/index/CapabilityIndex.java
@@ -110,7 +110,7 @@ public class CapabilityIndex extends Index<IInstallableUnit> {
// index usage query
//
IMatchExpression<IInstallableUnit> rm = ((IRequirement) rhsObj).getMatches();
- return RequiredCapability.isSimpleRequirement(rm) ? concatenateUnique(queriedKeys, rm.getParameters()[0]) : getRequirementIDs(rm.createContext(), ((Unary) rm).operand, queriedKeys);
+ return RequiredCapability.isVersionRangeRequirement(rm) ? concatenateUnique(queriedKeys, rm.getParameters()[0]) : getRequirementIDs(rm.createContext(), ((Unary) rm).operand, queriedKeys);
}
@Override
@@ -185,7 +185,7 @@ public class CapabilityIndex extends Index<IInstallableUnit> {
// index usage query
//
IMatchExpression<IInstallableUnit> rm = ((IRequirement) rhsObj).getMatches();
- queriedKeys = RequiredCapability.isSimpleRequirement(rm) ? concatenateUnique(queriedKeys, rm.getParameters()[0]) : getRequirementIDs(rm.createContext(), ((Unary) rm).operand, queriedKeys);
+ queriedKeys = RequiredCapability.isVersionRangeRequirement(rm) ? concatenateUnique(queriedKeys, rm.getParameters()[0]) : getRequirementIDs(rm.createContext(), ((Unary) rm).operand, queriedKeys);
break;
default :
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/messages.properties b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/messages.properties
index aa3b72b2e..ac979c288 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/messages.properties
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/messages.properties
@@ -60,7 +60,7 @@ premature_end_of_format=Premature end of format
premature_end_of_format_expected_0=Premature end of format, "{0}" expected
premature_EOS_0=Premature end of string in "{0}"
provided_capability_name_not_defined=the name of provided capability "{0}" is not defined
-provided_capability_namespace_not_defined=the namespace of the provided capabilty is not defined
+provided_capability_namespace_not_defined=the namespace of the provided capability is not defined
range_defined_more_then_once=Range defined more then once
range_max_cannot_be_less_then_range_min=The range maximum must not be less then its minimum
range_max_cannot_be_zero=The range maximum cannot be zero
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/IProvidedCapability.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/IProvidedCapability.java
index de61165eb..7cf08a170 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/IProvidedCapability.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/IProvidedCapability.java
@@ -6,11 +6,13 @@
*
* Contributors:
* EclipseSource - initial API and implementation
- * IBM - ongoing development
+* IBM - ongoing development
+* Todor Boev
******************************************************************************/
package org.eclipse.equinox.p2.metadata;
import java.util.Map;
+import org.eclipse.equinox.p2.metadata.expression.IFilterExpression;
/**
* Describes a capability that is exposed by an installable unit. These capabilities
@@ -29,45 +31,56 @@ import java.util.Map;
*/
public interface IProvidedCapability {
/**
+ * The name of the property under which the capability version is stored.
+ *
+ * Can be used with {@link #getProperties()}. The same value can be obtained with {@link #getVersion()}
+ *
+ * @since 2.4
+ */
+ String PROPERTY_VERSION = "version"; //$NON-NLS-1$
+
+ /**
*
* @return String the namespace of this capability.
* @noreference This method is not intended to be referenced by clients.
*/
- public String getNamespace();
+ String getNamespace();
/**
*
- * @return String the attribute stored under a key equal to {@link #getNamespace()} attribute of this capability.
+ * @return String the attribute stored under a key equal to the {@link #getNamespace()} attribute of this capability.
* @noreference This method is not intended to be referenced by clients.
*/
- public String getName();
+ String getName();
/**
*
- * @return String the special <code>version</code> attribute of this capability.
+ * @return String the special {@link #PROPERTY_VERSION} attribute of this capability.
* @noreference This method is not intended to be referenced by clients.
*/
- public Version getVersion();
+ Version getVersion();
/**
+ * A full description of this capability including the name and the version.
+ * <p>
+ * Such a description can be used to match this capability with an {@link IFilterExpression LDAP filter} for example.
*
- * @return A full description of this capability
+ * @return An unmodifiable map
* @noreference This method is not intended to be referenced by clients.
* @since 2.4
*/
- public Map<String, Object> getAttributes();
+ Map<String, Object> getProperties();
/**
* Returns whether this provided capability is equal to the given object.
*
* This method returns <i>true</i> if:
* <ul>
- * <li> Both this object and the given object are of type IProvidedCapability
- * <li> The result of <b>getNamespace()</b> on both objects are equal
- * <li> The result of <b>getAttributes()</b> on both objects are equal
+ * <li>Both this object and the given object are of type IProvidedCapability</li>
+ * <li>The result of {@link #getNamespace()} on both objects are equal</li>
+ * <li>The result of {@link #getProperties()} on both objects are equal</li>
* </ul>
*/
@Override
- public boolean equals(Object other);
-
+ boolean equals(Object other);
} \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/MetadataFactory.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/MetadataFactory.java
index e3f89b18d..6c9d91a77 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/MetadataFactory.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/metadata/MetadataFactory.java
@@ -30,6 +30,7 @@ import org.eclipse.equinox.internal.p2.metadata.InstallableUnitPatch;
import org.eclipse.equinox.internal.p2.metadata.License;
import org.eclipse.equinox.internal.p2.metadata.ProvidedCapability;
import org.eclipse.equinox.internal.p2.metadata.RequiredCapability;
+import org.eclipse.equinox.internal.p2.metadata.RequiredPropertiesMatch;
import org.eclipse.equinox.internal.p2.metadata.Requirement;
import org.eclipse.equinox.internal.p2.metadata.RequirementChange;
import org.eclipse.equinox.internal.p2.metadata.ResolvedInstallableUnit;
@@ -37,6 +38,8 @@ import org.eclipse.equinox.internal.p2.metadata.TouchpointData;
import org.eclipse.equinox.internal.p2.metadata.TouchpointInstruction;
import org.eclipse.equinox.internal.p2.metadata.TouchpointType;
import org.eclipse.equinox.internal.p2.metadata.UpdateDescriptor;
+import org.eclipse.equinox.p2.metadata.expression.ExpressionUtil;
+import org.eclipse.equinox.p2.metadata.expression.IFilterExpression;
import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
/**
@@ -461,11 +464,29 @@ public final class MetadataFactory {
* Returns a {@link IProvidedCapability} with the given values.
*
* @param namespace The capability namespace
- * @param attributes The description of the capability
+ * @param properties The description of the capability
* @since 2.4
*/
- public static IProvidedCapability createProvidedCapability(String namespace, Map<String, Object> attributes) {
- return new ProvidedCapability(namespace, attributes);
+ public static IProvidedCapability createProvidedCapability(String namespace, Map<String, Object> properties) {
+ return new ProvidedCapability(namespace, properties);
+ }
+
+ /**
+ * Create and return a new requirement ({@link IRequirement}) with the specified values.
+ *
+ * @param namespace the namespace for the requirement. Must not be <code>null</code>.
+ * @param name the name for the requirement. Must not be <code>null</code>.
+ * @param range the version range. A value of <code>null</code> is equivalent to {@link VersionRange#emptyRange} and matches all versions.
+ * @param filter The filter used to evaluate whether this capability is applicable in the
+ * current environment, or <code>null</code> to indicate this capability is always applicable
+ * @param optional <code>true</code> if this requirement is optional, and <code>false</code> otherwise.
+ * @param multiple <code>true</code> if this requirement can be satisfied by multiple provided capabilities, or <code>false</code>
+ * if it requires exactly one match
+ * @param greedy <code>true</code> if the requirement should be considered greedy and <code>false</code> otherwise
+ * @return the requirement
+ */
+ public static IRequirement createRequirement(String namespace, String name, VersionRange range, String filter, boolean optional, boolean multiple, boolean greedy) {
+ return new RequiredCapability(namespace, name, range, InstallableUnit.parseFilter(filter), optional ? 0 : 1, multiple ? Integer.MAX_VALUE : 1, greedy, null);
}
/**
@@ -507,87 +528,81 @@ public final class MetadataFactory {
/**
* Create and return a new requirement ({@link IRequirement}) with the specified values.
*
- * @param requirement the match expression
+ * @param namespace the namespace for the requirement. Must not be <code>null</code>.
+ * @param name the name for the requirement. Must not be <code>null</code>.
+ * @param range the version range. A value of <code>null</code> is equivalent to {@link VersionRange#emptyRange} and matches all versions.
* @param filter The filter used to evaluate whether this capability is applicable in the
* current environment, or <code>null</code> to indicate this capability is always applicable
* @param minCard minimum cardinality
* @param maxCard maximum cardinality
* @param greedy <code>true</code> if the requirement should be considered greedy and <code>false</code> otherwise
+ * @param description a <code>String</code> description of the requirement, or <code>null</code>
* @return the requirement
*/
- public static IRequirement createRequirement(IMatchExpression<IInstallableUnit> requirement, IMatchExpression<IInstallableUnit> filter, int minCard, int maxCard, boolean greedy) {
- // IRequiredCapability is simply a requirement with a match expression derived from a (namespace, name, version) tripet.
- // However the xml format also requires that maxCard > 1 or it is serialized in the generic format.
- // When parsing back from xml try to convert to an IRequiredCapability to retain the representation prior to serialization
- if (RequiredCapability.isSimpleRequirement(requirement)) {
- String namespace = RequiredCapability.extractNamespace(requirement);
- String name = RequiredCapability.extractName(requirement);
- VersionRange range = RequiredCapability.extractRange(requirement);
- return new RequiredCapability(namespace, name, range, filter, minCard, maxCard, greedy, null);
- }
+ public static IRequirement createRequirement(String namespace, String name, VersionRange range, IMatchExpression<IInstallableUnit> filter, int minCard, int maxCard, boolean greedy, String description) {
+ return new RequiredCapability(namespace, name, range, filter, minCard, maxCard, greedy, description);
+ }
- return new Requirement(requirement, filter, minCard, maxCard, greedy, null);
+ /**
+ *
+ * @param namespace
+ * @param propsFilter filter applied on {@link IProvidedCapability#getProperties()} of every {@link IInstallableUnit#getProvidedCapabilities()}
+ * @param envFilter matcher over {@link IInstallableUnit#getProperties()}
+ * @param minCard
+ * @param maxCard
+ * @param greedy
+ * @return the requirement
+ * @since 2.4
+ */
+ public static IRequirement createRequirement(String namespace, String propsFilter, IMatchExpression<IInstallableUnit> envFilter, int minCard, int maxCard, boolean greedy) {
+ IFilterExpression attrFilterExpr = ExpressionUtil.parseLDAP(propsFilter);
+ return new RequiredPropertiesMatch(namespace, attrFilterExpr, envFilter, minCard, maxCard, greedy, null);
}
/**
- * Create and return a new requirement ({@link IRequirement}) with the specified values.
*
- * @param namespace the namespace for the requirement. Must not be <code>null</code>.
- * @param name the name for the requirement. Must not be <code>null</code>.
- * @param range the version range. A value of <code>null</code> is equivalent to {@link VersionRange#emptyRange} and matches all versions.
- * @param filter The filter used to evaluate whether this capability is applicable in the
- * current environment, or <code>null</code> to indicate this capability is always applicable
- * @param optional <code>true</code> if this requirement is optional, and <code>false</code> otherwise.
- * @param multiple <code>true</code> if this requirement can be satisfied by multiple provided capabilities, or <code>false</code>
- * if it requires exactly one match
- * @param greedy <code>true</code> if the requirement should be considered greedy and <code>false</code> otherwise
+ * @param namespace
+ * @param propsFilter
+ * @param envFilter
+ * @param minCard
+ * @param maxCard
+ * @param greedy
+ * @param description
* @return the requirement
+ * @since 2.4
*/
- public static IRequirement createRequirement(String namespace, String name, VersionRange range, String filter, boolean optional, boolean multiple, boolean greedy) {
- return new RequiredCapability(namespace, name, range, InstallableUnit.parseFilter(filter), optional ? 0 : 1, multiple ? Integer.MAX_VALUE : 1, greedy, null);
+ public static IRequirement createRequirement(String namespace, IFilterExpression propsFilter, IMatchExpression<IInstallableUnit> envFilter, int minCard, int maxCard, boolean greedy, String description) {
+ return new RequiredPropertiesMatch(namespace, propsFilter, envFilter, minCard, maxCard, greedy, null);
}
/**
* Create and return a new requirement ({@link IRequirement}) with the specified values.
*
- * @param namespace the namespace for the requirement. Must not be <code>null</code>.
- * @param name the name for the requirement. Must not be <code>null</code>.
- * @param range the version range. A value of <code>null</code> is equivalent to {@link VersionRange#emptyRange} and matches all versions.
- * @param filter The filter used to evaluate whether this capability is applicable in the
+ * @param requirement the match expression
+ * @param envFilter The filter used to evaluate whether this capability is applicable in the
* current environment, or <code>null</code> to indicate this capability is always applicable
* @param minCard minimum cardinality
* @param maxCard maximum cardinality
* @param greedy <code>true</code> if the requirement should be considered greedy and <code>false</code> otherwise
- * @param description a <code>String</code> description of the requirement, or <code>null</code>
* @return the requirement
*/
- public static IRequirement createRequirement(String namespace, String name, VersionRange range, IMatchExpression<IInstallableUnit> filter, int minCard, int maxCard, boolean greedy, String description) {
- return new RequiredCapability(namespace, name, range, filter, minCard, maxCard, greedy, description);
+ public static IRequirement createRequirement(IMatchExpression<IInstallableUnit> requirement, IMatchExpression<IInstallableUnit> envFilter, int minCard, int maxCard, boolean greedy) {
+ return createRequirementInternal(requirement, envFilter, minCard, maxCard, greedy, null);
}
/**
* Create and return a new requirement ({@link IRequirement}) with the specified values.
*
* @param requirement the match expression
- * @param filter the filter, or <code>null</code>
+ * @param envFilter the filter, or <code>null</code>
* @param minCard minimum cardinality
* @param maxCard maximum cardinality
* @param greedy <code>true</code> if the requirement should be considered greedy and <code>false</code> otherwise
* @param description a <code>String</code> description of the requirement, or <code>null</code>
* @return the requirement
*/
- public static IRequirement createRequirement(IMatchExpression<IInstallableUnit> requirement, IMatchExpression<IInstallableUnit> filter, int minCard, int maxCard, boolean greedy, String description) {
- // IRequiredCapability is simply a requirement with a match expression derived from a (namespace, name, version) tripet.
- // However the xml format also requires that maxCard > 1 or it is serialized in the generic format.
- // When parsing back from xml try to convert to an IRequiredCapability to retain the representation prior to serialization
- if (RequiredCapability.isSimpleRequirement(requirement)) {
- String namespace = RequiredCapability.extractNamespace(requirement);
- String name = RequiredCapability.extractName(requirement);
- VersionRange range = RequiredCapability.extractRange(requirement);
- return new RequiredCapability(namespace, name, range, filter, minCard, maxCard, greedy, description);
- }
-
- return new Requirement(requirement, filter, minCard, maxCard, greedy, description);
+ public static IRequirement createRequirement(IMatchExpression<IInstallableUnit> requirement, IMatchExpression<IInstallableUnit> envFilter, int minCard, int maxCard, boolean greedy, String description) {
+ return createRequirementInternal(requirement, envFilter, minCard, maxCard, greedy, description);
}
/**
@@ -737,6 +752,14 @@ public final class MetadataFactory {
}
}
+ /**
+ *
+ * @param descriptors
+ * @param severity
+ * @param description
+ * @param location
+ * @return A new update descriptor
+ */
public static IUpdateDescriptor createUpdateDescriptor(Collection<IMatchExpression<IInstallableUnit>> descriptors, int severity, String description, URI location) {
return new UpdateDescriptor(descriptors, severity, description, location);
}
@@ -770,6 +793,26 @@ public final class MetadataFactory {
return createUpdateDescriptor(descriptors, severity, description, location);
}
+ private static IRequirement createRequirementInternal(IMatchExpression<IInstallableUnit> requirement, IMatchExpression<IInstallableUnit> envFilter, int minCard, int maxCard, boolean greedy, String description) {
+ // IRequiredCapability is simply a requirement with a match expression derived from a (namespace, name, version) tripet.
+ // However the xml format also requires that maxCard > 1 or it is serialized in the generic format.
+ // When parsing back from xml try to convert to an IRequiredCapability to retain the representation prior to serialization
+ if (RequiredCapability.isVersionRangeRequirement(requirement)) {
+ String namespace = RequiredCapability.extractNamespace(requirement);
+ String name = RequiredCapability.extractName(requirement);
+ VersionRange range = RequiredCapability.extractRange(requirement);
+ return new RequiredCapability(namespace, name, range, envFilter, minCard, maxCard, greedy, description);
+ }
+
+ if (RequiredPropertiesMatch.isPropertiesMatchRequirement(requirement)) {
+ String namespace = RequiredPropertiesMatch.extractNamespace(requirement);
+ IFilterExpression attrMatch = RequiredPropertiesMatch.extractPropertiesMatch(requirement);
+ return new RequiredPropertiesMatch(namespace, attrMatch, envFilter, minCard, maxCard, greedy, description);
+ }
+
+ return new Requirement(requirement, envFilter, minCard, maxCard, greedy, description);
+ }
+
private static ITouchpointType getCachedTouchpointType(String id, Version version) {
for (int i = 0; i < typeCache.length; i++) {
if (typeCache[i] != null && typeCache[i].getId().equals(id) && typeCache[i].getVersion().equals(version))
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 5ff218a9e..36dbe0f51 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
@@ -39,6 +39,8 @@ Import-Package: org.eclipse.equinox.app;version="[1.0.0,2.0.0)",
org.eclipse.osgi.service.resolver;version="1.5.0",
org.eclipse.osgi.util;version="1.1.0",
org.osgi.framework;version="1.3.0",
+ org.osgi.framework.wiring;version="1.2.0",
+ org.osgi.resource;version="1.0.0",
org.osgi.service.application;version="1.1.0",
org.osgi.service.packageadmin;version="1.2.0"
Export-Package: org.eclipse.equinox.internal.p2.publisher.compatibility;x-internal:=true,
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 b3411b045..c2ec094be 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
@@ -12,6 +12,9 @@
******************************************************************************/
package org.eclipse.equinox.p2.publisher.eclipse;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toMap;
+
import java.io.*;
import java.util.*;
import java.util.Map.Entry;
@@ -28,7 +31,7 @@ import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription;
import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitFragmentDescription;
import org.eclipse.equinox.p2.metadata.VersionRange;
-import org.eclipse.equinox.p2.metadata.expression.*;
+import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
import org.eclipse.equinox.p2.publisher.*;
import org.eclipse.equinox.p2.publisher.actions.*;
import org.eclipse.equinox.p2.query.IQueryResult;
@@ -43,6 +46,8 @@ import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.internal.publishing.Activator;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.resource.Namespace;
/**
* Publish IUs for all of the bundles in a given set of locations or described by a set of
@@ -78,7 +83,6 @@ public class BundlesAction extends AbstractPublisherAction {
public static final String OSGI_BUNDLE_CLASSIFIER = "osgi.bundle"; //$NON-NLS-1$
public static final String CAPABILITY_NS_OSGI_BUNDLE = "osgi.bundle"; //$NON-NLS-1$
public static final String CAPABILITY_NS_OSGI_FRAGMENT = "osgi.fragment"; //$NON-NLS-1$
- public static final String CAPABILITY_ATTR_VERSION = "version"; //$NON-NLS-1$
public static final IProvidedCapability BUNDLE_CAPABILITY = MetadataFactory.createProvidedCapability(PublisherHelper.NAMESPACE_ECLIPSE_TYPE, TYPE_ECLIPSE_BUNDLE, Version.createOSGi(1, 0, 0));
public static final IProvidedCapability SOURCE_BUNDLE_CAPABILITY = MetadataFactory.createProvidedCapability(PublisherHelper.NAMESPACE_ECLIPSE_TYPE, TYPE_ECLIPSE_SOURCE, Version.createOSGi(1, 0, 0));
@@ -194,7 +198,7 @@ public class BundlesAction extends AbstractPublisherAction {
// Process generic requirements
ManifestElement[] rawRequireCapHeader = parseManifestHeader(Constants.REQUIRE_CAPABILITY, manifest, bd.getLocation());
for (GenericSpecification requiredCap : bd.getGenericRequires()) {
- addGenericRequirement(requirements, requiredCap, rawRequireCapHeader);
+ addRequirement(requirements, requiredCap, rawRequireCapHeader);
}
iu.setRequirements(requirements.toArray(new IRequirement[requirements.size()]));
@@ -223,7 +227,7 @@ public class BundlesAction extends AbstractPublisherAction {
int capNo = 0;
for (GenericDescription genericCap : bd.getGenericCapabilities()) {
- addGenericCapability(providedCapabilities, genericCap, iu, capNo);
+ addCapability(providedCapabilities, genericCap, iu, capNo);
capNo++;
}
@@ -301,36 +305,45 @@ public class BundlesAction extends AbstractPublisherAction {
reqsDeps.add(MetadataFactory.createRequirement(PublisherHelper.CAPABILITY_NS_JAVA_PACKAGE, importSpec.getName(), versionRange, null, optional, false, greedy));
}
- // TODO Handle all attributes and directives somehow? Especially the "effective" directive.
- protected void addGenericRequirement(List<IRequirement> reqsDeps, GenericSpecification requireCapSpec, ManifestElement[] rawRequiresPackageHeader) {
- String ns = requireCapSpec.getType();
- String ldap = requireCapSpec.getMatchingFilter();
- String matcher = "providedCapabilities.exists(pc | pc.namespace == '" + ns + "' && pc.attributes ~= filter('" + ldap + "'))"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-
- IExpression expr = ExpressionUtil.parse(matcher);
- IMatchExpression<IInstallableUnit> matchExpr = ExpressionUtil.getFactory().matchExpression(expr);
-
- // Optional and greedy in order to be backward compatible.
- IRequirement requireCap = MetadataFactory.createRequirement(matchExpr, null, 0, 1, true);
-
- reqsDeps.add(requireCap);
- }
-
protected void addRequireBundleRequirement(List<IRequirement> reqsDeps, BundleSpecification requiredBundle, ManifestElement[] rawRequireBundleHeader) {
final boolean optional = requiredBundle.isOptional();
final boolean greedy;
- if (optional)
+ if (optional) {
greedy = INSTALLATION_GREEDY.equals(getInstallationDirective(requiredBundle.getName(), rawRequireBundleHeader));
- else
+ } else {
greedy = true;
+ }
reqsDeps.add(MetadataFactory.createRequirement(CAPABILITY_NS_OSGI_BUNDLE, requiredBundle.getName(), PublisherHelper.fromOSGiVersionRange(requiredBundle.getVersionRange()), null, optional ? 0 : 1, 1, greedy));
}
- protected void addGenericCapability(List<IProvidedCapability> caps, GenericDescription provideCapDesc, InstallableUnitDescription iu, int capNo) {
+ // TODO Handle the "effective:=" directive somehow?
+ protected void addRequirement(List<IRequirement> reqsDeps, GenericSpecification requireCapSpec, ManifestElement[] rawRequireCapabilities) {
+ BundleRequirement req = requireCapSpec.getRequirement();
+
+ String namespace = req.getNamespace();
+ Map<String, String> 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, greedy);
+ reqsDeps.add(requireCap);
+ }
+
+ protected void addCapability(List<IProvidedCapability> caps, GenericDescription provideCapDesc, InstallableUnitDescription iu, int capNo) {
+ // Convert the values to String, Version, List of String or Version
+ Map<String, Object> capAttrs = provideCapDesc.getDeclaredAttributes()
+ .entrySet()
+ .stream()
+ .collect(toMap(Entry::getKey, e -> convertAttribute(e.getValue())));
+
+ // Resolve the namespace
String capNs = provideCapDesc.getType();
- Map<String, Object> capAttrs = new HashMap<>(provideCapDesc.getDeclaredAttributes());
- // Resolve the p2 name
+ // Resolve the mandatory p2 name
// By convention OSGi capabilities have an attribute named like the capability namespace.
// If this is not the case synthesize a unique name (e.g. "osgi.service" has an "objectClass" attribute instead).
// TODO If present but not a String log a warning somehow that it is ignored? Or fail the publication?
@@ -338,28 +351,32 @@ public class BundlesAction extends AbstractPublisherAction {
capNs,
(k, v) -> (v instanceof String) ? v : String.format("%s_%s-%s", iu.getId(), iu.getVersion(), capNo)); //$NON-NLS-1$
- // Convert all OSGi versions to P2 versions
- for (String key : new HashSet<>(capAttrs.keySet())) {
- Object val = capAttrs.get(key);
- if (!(val instanceof org.osgi.framework.Version)) {
- continue;
- }
- org.osgi.framework.Version osgiVer = (org.osgi.framework.Version) val;
- Version p2Ver = Version.createOSGi(osgiVer.getMajor(), osgiVer.getMinor(), osgiVer.getMicro(), osgiVer.getQualifier());
- capAttrs.put(key, p2Ver);
- }
-
- // Resolve the version
+ // Resolve the mandatory p2 version
// By convention versioned OSGi capabilities have a "version" attribute containing the OSGi Version object
// If this is not the case use an empty version (e.g. "osgi.ee" has a list of versions).
// TODO If present but not a Version log a warning somehow that it is ignored? Or fail the publication?
capAttrs.compute(
- CAPABILITY_ATTR_VERSION,
+ IProvidedCapability.PROPERTY_VERSION,
(k, v) -> (v instanceof Version) ? v : Version.emptyVersion);
caps.add(MetadataFactory.createProvidedCapability(capNs, capAttrs));
}
+ private Object convertAttribute(Object attr) {
+ if (attr instanceof Collection<?>) {
+ return ((Collection<?>) attr).stream().map(this::convertScalarAttribute).collect(toList());
+ }
+ return convertScalarAttribute(attr);
+ }
+
+ private Object convertScalarAttribute(Object attr) {
+ if (attr instanceof org.osgi.framework.Version) {
+ org.osgi.framework.Version osgiVer = (org.osgi.framework.Version) attr;
+ return Version.createOSGi(osgiVer.getMajor(), osgiVer.getMinor(), osgiVer.getMicro(), osgiVer.getQualifier());
+ }
+ return attr.toString();
+ }
+
static VersionRange computeUpdateRange(org.osgi.framework.Version base) {
VersionRange updateRange = null;
if (!base.equals(org.osgi.framework.Version.emptyVersion)) {
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/AbstractPublisherAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/AbstractPublisherAction.java
index 71288480a..33822347f 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/AbstractPublisherAction.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/p2/publisher/AbstractPublisherAction.java
@@ -395,7 +395,7 @@ public abstract class AbstractPublisherAction implements IPublisherAction {
}
IRequiredCapability requiredCapability = (IRequiredCapability) requirement;
- if (!RequiredCapability.isSimpleRequirement(requiredCapability.getMatches())) {
+ if (!RequiredCapability.isVersionRangeRequirement(requiredCapability.getMatches())) {
return null;
}
diff --git a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/persistence/XMLConstants.java b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/persistence/XMLConstants.java
index f1af9f142..de1601d90 100644
--- a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/persistence/XMLConstants.java
+++ b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/persistence/XMLConstants.java
@@ -11,6 +11,9 @@
*******************************************************************************/
package org.eclipse.equinox.internal.p2.persistence;
+import java.util.List;
+import org.eclipse.equinox.p2.metadata.Version;
+
public interface XMLConstants {
// Constants used in defining a default processing instruction
@@ -29,7 +32,20 @@ public interface XMLConstants {
public static final String PROPERTY_ELEMENT = "property"; //$NON-NLS-1$
public static final String PROPERTY_NAME_ATTRIBUTE = "name"; //$NON-NLS-1$
public static final String PROPERTY_VALUE_ATTRIBUTE = "value"; //$NON-NLS-1$
+ public static final String PROPERTY_TYPE_ATTRIBUTE = "type"; //$NON-NLS-1$
public static final String[] PROPERTY_ATTRIBUTES = new String[] {PROPERTY_NAME_ATTRIBUTE, PROPERTY_VALUE_ATTRIBUTE};
+ public static final String[] PROPERTY_OPTIONAL_ATTRIBUTES = new String[] {PROPERTY_TYPE_ATTRIBUTE};
+ public static final String PROPERTY_TYPE_LIST = List.class.getSimpleName();
+ public static final String PROPERTY_TYPE_STRING = String.class.getSimpleName();
+ public static final String PROPERTY_TYPE_INTEGER = Integer.class.getSimpleName();
+ public static final String PROPERTY_TYPE_LONG = Long.class.getSimpleName();
+ public static final String PROPERTY_TYPE_FLOAT = Float.class.getSimpleName();
+ public static final String PROPERTY_TYPE_DOUBLE = Double.class.getSimpleName();
+ public static final String PROPERTY_TYPE_BYTE = Byte.class.getSimpleName();
+ public static final String PROPERTY_TYPE_SHORT = Short.class.getSimpleName();
+ public static final String PROPERTY_TYPE_CHARACTER = Character.class.getSimpleName();
+ public static final String PROPERTY_TYPE_BOOLEAN = Boolean.class.getSimpleName();
+ public static final String PROPERTY_TYPE_VERSION = Version.class.getSimpleName();
// Constants for the names of common general attributes
public static final String ID_ATTRIBUTE = "id"; //$NON-NLS-1$
diff --git a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/persistence/XMLWriter.java b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/persistence/XMLWriter.java
index 6973a2f06..3a532f6ad 100644
--- a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/persistence/XMLWriter.java
+++ b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/persistence/XMLWriter.java
@@ -10,11 +10,11 @@
*******************************************************************************/
package org.eclipse.equinox.internal.p2.persistence;
+import static java.util.stream.Collectors.joining;
+
import java.io.*;
import java.nio.charset.StandardCharsets;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Stack;
+import java.util.*;
import org.eclipse.equinox.p2.metadata.Version;
public class XMLWriter implements XMLConstants {
@@ -220,28 +220,82 @@ public class XMLWriter implements XMLConstants {
this.pw.flush();
}
- public void writeProperties(Map<String, String> properties) {
+ public void writeProperties(Map<String, ?> properties) {
writeProperties(PROPERTIES_ELEMENT, properties);
}
- public void writeProperties(String propertiesElement, Map<String, String> properties) {
- if (properties != null && properties.size() > 0) {
- start(propertiesElement);
- attribute(COLLECTION_SIZE_ATTRIBUTE, properties.size());
- for (Entry<String, String> entry : properties.entrySet()) {
- writeProperty(entry.getKey(), entry.getValue());
- }
- end(propertiesElement);
+ public void writeProperties(String propertiesElement, Map<String, ?> properties) {
+ if (properties == null || properties.isEmpty()) {
+ return;
}
+
+ start(propertiesElement);
+ attribute(COLLECTION_SIZE_ATTRIBUTE, properties.size());
+ properties.forEach(this::writeProperty);
+ end();
}
- public void writeProperty(String name, String value) {
+ public void writeProperty(String name, Object value) {
+ String type;
+ String valueStr;
+
+ if (Collection.class.isAssignableFrom(value.getClass())) {
+ Collection<?> coll = (Collection<?>) value;
+
+ type = PROPERTY_TYPE_LIST;
+ String elType = resolvePropertyType(coll.iterator().next());
+ if (elType != null) {
+ type += String.format("<%s>", elType); //$NON-NLS-1$
+ }
+
+ valueStr = coll.stream().map(Object::toString).collect(joining(",")); //$NON-NLS-1$
+ } else {
+ type = resolvePropertyType(value);
+ valueStr = value.toString();
+ }
+
start(PROPERTY_ELEMENT);
attribute(PROPERTY_NAME_ATTRIBUTE, name);
- attribute(PROPERTY_VALUE_ATTRIBUTE, value);
+ attribute(PROPERTY_VALUE_ATTRIBUTE, valueStr);
+ attributeOptional(PROPERTY_TYPE_ATTRIBUTE, type);
end();
}
+ private String resolvePropertyType(Object value) {
+ if (value instanceof Integer) {
+ return PROPERTY_TYPE_INTEGER;
+ }
+ if (value instanceof Long) {
+ return PROPERTY_TYPE_LONG;
+ }
+ if (value instanceof Float) {
+ return PROPERTY_TYPE_FLOAT;
+ }
+ if (value instanceof Double) {
+ return PROPERTY_TYPE_DOUBLE;
+ }
+ if (value instanceof Byte) {
+ return PROPERTY_TYPE_BYTE;
+ }
+ if (value instanceof Short) {
+ return PROPERTY_TYPE_SHORT;
+ }
+ if (value instanceof Character) {
+ return PROPERTY_TYPE_CHARACTER;
+ }
+ if (value instanceof Boolean) {
+ return PROPERTY_TYPE_BOOLEAN;
+ }
+ if (value instanceof Version) {
+ return PROPERTY_TYPE_VERSION;
+ }
+
+ // Null is read back as String
+ // NOTE: Using string as default is needed for backward compatibility with properties that are always String like
+ // the IU properties
+ return null;
+ }
+
protected static String attributeImage(String name, String value) {
if (value == null) {
return ""; // optional attribute with no value //$NON-NLS-1$
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/director/AutomatedDirectorTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/director/AutomatedDirectorTest.java
index f229b4e66..d726d6a5b 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/director/AutomatedDirectorTest.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/director/AutomatedDirectorTest.java
@@ -10,14 +10,16 @@ package org.eclipse.equinox.p2.tests.director;
import java.util.HashMap;
import java.util.Map;
-import junit.framework.Test;
-import junit.framework.TestSuite;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
import org.eclipse.equinox.internal.provisional.p2.director.IDirector;
import org.eclipse.equinox.p2.engine.IProfile;
-import org.eclipse.equinox.p2.metadata.*;
+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.Version;
import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
import org.eclipse.equinox.p2.tests.AbstractProvisioningTest;
@@ -25,20 +27,6 @@ import org.eclipse.equinox.p2.tests.AbstractProvisioningTest;
* Various automated tests of the {@link IDirector} API.
*/
public class AutomatedDirectorTest extends AbstractProvisioningTest {
- //private static Version version = Version.createOSGi(1, 0, 0);
-
- public static Test suite() {
- return new TestSuite(AutomatedDirectorTest.class);
- }
-
- public AutomatedDirectorTest() {
- super("");
- }
-
- public AutomatedDirectorTest(String name) {
- super(name);
- }
-
/**
* Tests installing an IU that has a filtered dependency on another IU. When
* the filter is satisfied, the dependency is active and the required IU should
@@ -46,26 +34,39 @@ public class AutomatedDirectorTest extends AbstractProvisioningTest {
* and the second IU should not be installed.
*/
public void testInstallFilteredCapability() {
- //The IU that is required
+ final String envKey = "filterKey";
+ final String envVal = "true";
+
+ // The IU that is required
IInstallableUnit requiredIU = createIU("required." + getName());
// The IU to be installed
- IMatchExpression<IInstallableUnit> filter = createFilter("FilterKey", "true");
- IRequirement capability = MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, requiredIU.getId(), ANY_VERSION, filter, false, false);
- IInstallableUnit toInstallIU = createIU("toInstall." + getName(), new IRequirement[] {capability});
+ IMatchExpression<IInstallableUnit> requirementFilter = createFilter(envKey, envVal);
+ IRequirement[] requires = new IRequirement[] {
+ MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, requiredIU.getId(), ANY_VERSION, requirementFilter, false, false)
+ };
+ IInstallableUnit toInstallIU = createIU("toInstall." + getName(), requires);
+ // Metadata repository
IInstallableUnit[] allUnits = new IInstallableUnit[] {requiredIU, toInstallIU};
createTestMetdataRepository(allUnits);
- IDirector director = createDirector();
- //Install into a profile in which the filter is satisfied
+ // Install into a profile in which the requirement filter is satisfied
Map<String, String> properties = new HashMap<>();
- properties.put(IProfile.PROP_ENVIRONMENTS, "FilterKey=true");
+ properties.put(IProfile.PROP_ENVIRONMENTS, envKey + "=" + envVal);
+
+ // Profile
IProfile satisfied = createProfile("Satisfied." + getName(), properties);
+
+ // Profile change request
ProfileChangeRequest request = new ProfileChangeRequest(satisfied);
request.add(toInstallIU);
+
+ // Provision
+ IDirector director = createDirector();
IStatus result = director.provision(request, null, null);
- assertTrue("1.0", result.isOK());
+
+ assertTrue(result.isOK());
assertProfileContains("1.1", satisfied, allUnits);
}
@@ -73,25 +74,41 @@ public class AutomatedDirectorTest extends AbstractProvisioningTest {
* Tests installing an IU that has an optional prerequisite that is available.
*/
public void testInstallOptionalAvailable() {
- String capabilityId = "test." + getName();
+ final String capabilityNamespace = "test.capability";
+ final String capabilityName = "test." + getName();
+ final Version capabilityVersion = DEFAULT_VERSION;
+
//The IU that exports the capability
- IInstallableUnit requiredIU = createIU("required." + getName(), new IProvidedCapability[] {MetadataFactory.createProvidedCapability("test.capability", capabilityId, DEFAULT_VERSION)});
+ IProvidedCapability[] provides = new IProvidedCapability[] {
+ MetadataFactory.createProvidedCapability(capabilityNamespace, capabilityName, capabilityVersion)
+ };
+ IInstallableUnit requiredIU = createIU("required." + getName(), provides);
//The IU that optionally requires the capability
- IRequirement required = MetadataFactory.createRequirement("test.capability", capabilityId, ANY_VERSION, null, /* optional=> */true, /* multiple=> */false, /* greedy=>*/false);
- IInstallableUnit toInstallIU = createIU("toInstall." + getName(), new IRequirement[] {required});
+ IRequirement[] requires = new IRequirement[] {
+ MetadataFactory.createRequirement(capabilityNamespace, capabilityName, ANY_VERSION, null, /* optional=> */true, /* multiple=> */false, /* greedy=>*/false)
+ };
+ IInstallableUnit toInstallIU = createIU("toInstall." + getName(), requires);
+ // Metadata repository
IInstallableUnit[] allUnits = new IInstallableUnit[] {toInstallIU, requiredIU};
- IInstallableUnit[] toInstallArray = new IInstallableUnit[] {toInstallIU};
createTestMetdataRepository(allUnits);
IProfile profile = createProfile("TestProfile." + getName());
- IDirector director = createDirector();
+
+ // Change request
ProfileChangeRequest request = new ProfileChangeRequest(profile);
+ IInstallableUnit[] toInstallArray = new IInstallableUnit[] {toInstallIU};
request.addInstallableUnits(toInstallArray);
+
+ // Provision
+ IDirector director = createDirector();
IStatus result = director.provision(request, null, null);
- if (!result.isOK())
+ if (!result.isOK()) {
LogHelper.log(result);
+ }
+
+ // The requiredIu is not installed, because the optional requirement is not greedy
assertTrue("1.0", result.isOK());
assertProfileContains("1.1", profile, toInstallArray);
}
@@ -100,21 +117,34 @@ public class AutomatedDirectorTest extends AbstractProvisioningTest {
* Tests installing an IU that has an optional prerequisite that is not available.
*/
public void testInstallOptionalUnavailable() {
- String capabilityId = "test." + getName();
- //no IU will be available that exports this capability
- IRequirement required = MetadataFactory.createRequirement("test.capability", capabilityId, ANY_VERSION, null, true, false);
- IInstallableUnit toInstallIU = createIU("toInstall." + getName(), new IRequirement[] {required});
+ final String capabilityNamespace = "test.capability";
+ final String capabilityName = "test." + getName();
+
+ // no IU will be available that exports this capability
+ IRequirement[] requires = new IRequirement[] {
+ MetadataFactory.createRequirement(capabilityNamespace, capabilityName, ANY_VERSION, null, /* optional=> */true, /* multiple=> */false)
+ };
+ IInstallableUnit toInstallIU = createIU("toInstall." + getName(), requires);
+ // Metadata repo
IInstallableUnit[] allUnits = new IInstallableUnit[] {toInstallIU};
createTestMetdataRepository(allUnits);
+ // Profile
IProfile profile = createProfile("TestProfile." + getName());
- IDirector director = createDirector();
+
+ // Change request
ProfileChangeRequest request = new ProfileChangeRequest(profile);
request.addInstallableUnits(allUnits);
+
+ // Provision
+ IDirector director = createDirector();
IStatus result = director.provision(request, null, null);
- if (!result.isOK())
+ if (!result.isOK()) {
LogHelper.log(result);
+ }
+
+ // The UI is installed because the requirement is optional
assertTrue("1.0", result.isOK());
assertProfileContains("1.1", profile, allUnits);
}
@@ -124,30 +154,50 @@ public class AutomatedDirectorTest extends AbstractProvisioningTest {
* the capability has a platform filter that is not satisfied.
*/
public void testInstallPlatformFilter() {
- //The IU that exports the capability
- String capabilityId = "test." + getName();
- IProvidedCapability[] provides = new IProvidedCapability[] {MetadataFactory.createProvidedCapability("test.capability", capabilityId, DEFAULT_VERSION)};
- IInstallableUnit requiredIU = createIU("required." + getName(), createFilter("osgi.os", "blort"), provides);
+ // Profile environment
+ final String osKey = "osgi.os";
+ final String osVal = "blort";
+
+ // Test capability
+ final String capabilityNamespace = "test.capability";
+ final String capabilityName = "test." + getName();
+ final Version capabilityVersion = DEFAULT_VERSION;
- IInstallableUnit toInstallIU = createIU("toInstall." + getName(), createRequiredCapabilities("test.capability", capabilityId, ANY_VERSION, (IMatchExpression<IInstallableUnit>) null));
+ // The IU that exports the capability
+ IProvidedCapability[] provides = new IProvidedCapability[] {MetadataFactory.createProvidedCapability(capabilityNamespace, capabilityName, capabilityVersion)};
+ IInstallableUnit requiredIU = createIU("required." + getName(), createFilter(osKey, osVal), provides);
+ // Installed IU
+ IInstallableUnit toInstallIU = createIU("toInstall." + getName(), createRequiredCapabilities(capabilityNamespace, capabilityName, ANY_VERSION, (IMatchExpression<IInstallableUnit>) null));
+
+ // Metadata repo
IInstallableUnit[] allUnits = new IInstallableUnit[] {requiredIU, toInstallIU};
- IInstallableUnit[] toInstallArray = new IInstallableUnit[] {toInstallIU};
createTestMetdataRepository(allUnits);
- IProfile profile = createProfile("TestProfile." + getName());
IDirector director = createDirector();
+
+ // Profile that does not satisfy the OS requirement
+ IProfile profile = createProfile("TestProfile." + getName());
+
+ // Request
ProfileChangeRequest request = new ProfileChangeRequest(profile);
+ IInstallableUnit[] toInstallArray = new IInstallableUnit[] {toInstallIU};
request.addInstallableUnits(toInstallArray);
+
+ // Provision - should fail since requireIU can't be installed on the current environment
IStatus result = director.provision(request, null, null);
assertTrue("1.0", !result.isOK());
- //try again with the filter satisfied
+ // New profile that satisfies the OS requirement
Map<String, String> properties = new HashMap<>();
- properties.put(IProfile.PROP_ENVIRONMENTS, "osgi.os=blort");
- IProfile profile2 = createProfile("TestProfile2." + getName(), properties);
- request = new ProfileChangeRequest(profile2);
+ properties.put(IProfile.PROP_ENVIRONMENTS, osKey + "=" + osVal);
+ profile = createProfile("TestProfile2." + getName(), properties);
+
+ // New request
+ request = new ProfileChangeRequest(profile);
request.addInstallableUnits(toInstallArray);
+
+ // New provisioning - should succeed
result = director.provision(request, null, null);
assertTrue("2.0", result.isOK());
}
@@ -156,27 +206,42 @@ public class AutomatedDirectorTest extends AbstractProvisioningTest {
* Tests installing an IU that has an unsatisfied platform filter
*/
public void testInstallPlatformFilterUnsatisfied() {
- //The IU to install
- IInstallableUnit toInstallIU = createIU("toInstall." + getName(), createFilter("osgi.os", "blort"), NO_PROVIDES);
+ // Profile environment
+ final String osKey = "osgi.os";
+ final String osVal = "blort";
+
+ // The IU to install that needs a concrete environment
+ IInstallableUnit toInstallIU = createIU("toInstall." + getName(), createFilter(osKey, osVal), NO_PROVIDES);
+
+ // Metadata repo
IInstallableUnit[] allUnits = new IInstallableUnit[] {toInstallIU};
- IInstallableUnit[] toInstallArray = new IInstallableUnit[] {toInstallIU};
createTestMetdataRepository(allUnits);
+ // Profile without a matching environment
IProfile profile = createProfile("TestProfile." + getName());
- IDirector director = createDirector();
+
+ // Change request
ProfileChangeRequest request = new ProfileChangeRequest(profile);
+ IInstallableUnit[] toInstallArray = new IInstallableUnit[] {toInstallIU};
request.addInstallableUnits(toInstallArray);
+
+ // Provisioning failure: incompatible environment
+ IDirector director = createDirector();
IStatus result = director.provision(request, null, null);
- assertTrue("1.0", !result.isOK());
+ assertTrue(!result.isOK());
- //try again with the filter satisfied
+ // Profile with matching environment
Map<String, String> properties = new HashMap<>();
- properties.put(IProfile.PROP_ENVIRONMENTS, "osgi.os=blort");
- IProfile profile2 = createProfile("TestProfile2." + getName(), properties);
- request = new ProfileChangeRequest(profile2);
+ properties.put(IProfile.PROP_ENVIRONMENTS, osKey + "=" + osVal);
+ profile = createProfile("TestProfile2." + getName(), properties);
+
+ // New change request
+ request = new ProfileChangeRequest(profile);
request.addInstallableUnits(toInstallArray);
+
+ // Provisioning success
result = director.provision(request, null, null);
- assertTrue("2.0", result.isOK());
+ assertTrue(result.isOK());
}
/**
@@ -184,24 +249,39 @@ public class AutomatedDirectorTest extends AbstractProvisioningTest {
* that the IU providing the capability is installed.
*/
public void testSimpleInstallRequired() {
- String capabilityId = "test." + getName();
+ // Test capability
+ String capabilityNamespace = "test.capability";
+ String capabilityName = "test." + getName();
+
//The IU that exports the capability
- IInstallableUnit requiredIU = createIU("required." + getName(), new IProvidedCapability[] {MetadataFactory.createProvidedCapability("test.capability", capabilityId, DEFAULT_VERSION)});
+ IProvidedCapability[] provides = new IProvidedCapability[] {
+ MetadataFactory.createProvidedCapability(capabilityNamespace, capabilityName, DEFAULT_VERSION)
+ };
+ IInstallableUnit requiredIU = createIU("required." + getName(), provides);
- IInstallableUnit toInstallIU = createIU("toInstall." + getName(), createRequiredCapabilities("test.capability", capabilityId, ANY_VERSION, (IMatchExpression<IInstallableUnit>) null));
+ // The IU that requires the capability
+ IRequirement[] requires = createRequiredCapabilities(capabilityNamespace, capabilityName, ANY_VERSION, (IMatchExpression<IInstallableUnit>) null);
+ IInstallableUnit toInstallIU = createIU("toInstall." + getName(), requires);
+ // Crate the metadata repo
IInstallableUnit[] allUnits = new IInstallableUnit[] {requiredIU, toInstallIU};
- IInstallableUnit[] toInstallArray = new IInstallableUnit[] {toInstallIU};
createTestMetdataRepository(allUnits);
+ // Provision
IProfile profile = createProfile("TestProfile." + getName());
- IDirector director = createDirector();
+ // Create the profile change request
ProfileChangeRequest request = new ProfileChangeRequest(profile);
+ IInstallableUnit[] toInstallArray = new IInstallableUnit[] {toInstallIU};
request.addInstallableUnits(toInstallArray);
+
+ // Provision
+ IDirector director = createDirector();
IStatus result = director.provision(request, null, null);
- if (!result.isOK())
+ if (!result.isOK()) {
LogHelper.log(result);
+ }
+
assertTrue("1.0", result.isOK());
assertProfileContains("1.1", profile, allUnits);
}
@@ -211,24 +291,34 @@ public class AutomatedDirectorTest extends AbstractProvisioningTest {
* specifying a version range (any version will do).
*/
public void testInstallRequiredNoVersion() {
- //The IU that is needed
+ // The IU that is needed
IInstallableUnit requiredIU = createIU("required." + getName());
- IRequirement capability = MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, requiredIU.getId(), null, null, false, false);
- IInstallableUnit toInstallIU = createIU("toInstall." + getName(), new IRequirement[] {capability});
+ // The IU that is installed
+ IRequirement[] requires = new IRequirement[] {
+ MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, requiredIU.getId(), null, null, false, false)
+ };
+ IInstallableUnit toInstallIU = createIU("toInstall." + getName(), requires);
+ // Metadata repo
IInstallableUnit[] allUnits = new IInstallableUnit[] {requiredIU, toInstallIU};
- IInstallableUnit[] toInstallArray = new IInstallableUnit[] {toInstallIU};
createTestMetdataRepository(allUnits);
+ // Profile
IProfile profile = createProfile("TestProfile." + getName());
- IDirector director = createDirector();
+ // Profile change request
ProfileChangeRequest request = new ProfileChangeRequest(profile);
+ IInstallableUnit[] toInstallArray = new IInstallableUnit[] {toInstallIU};
request.addInstallableUnits(toInstallArray);
+
+ // Provision
+ IDirector director = createDirector();
IStatus result = director.provision(request, null, null);
- if (!result.isOK())
+ if (!result.isOK()) {
LogHelper.log(result);
+ }
+
assertTrue("1.0", result.isOK());
assertProfileContains("1.1", profile, allUnits);
}
@@ -239,25 +329,34 @@ public class AutomatedDirectorTest extends AbstractProvisioningTest {
* capability on the IU namespace.
*/
public void testSimpleInstallRequiredIU() {
- //The IU that exports the capability
+ // The IU that is required. It exports it's identity capability by default.
IInstallableUnit requiredIU = createIU("required." + getName());
- IRequirement capability = MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, requiredIU.getId(), ANY_VERSION, null, false, false);
- IInstallableUnit toInstallIU = createIU("toInstall." + getName(), new IRequirement[] {capability});
+ // The IU that is installed
+ IRequirement[] requires = new IRequirement[] {
+ MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, requiredIU.getId(), ANY_VERSION, null, false, false)
+ };
+ IInstallableUnit toInstallIU = createIU("toInstall." + getName(), requires);
+ // Create the metadata repo
IInstallableUnit[] allUnits = new IInstallableUnit[] {requiredIU, toInstallIU};
- IInstallableUnit[] toInstallArray = new IInstallableUnit[] {toInstallIU};
createTestMetdataRepository(allUnits);
IProfile profile = createProfile("TestProfile." + getName());
- IDirector director = createDirector();
+ // Create the profile change request
ProfileChangeRequest request = new ProfileChangeRequest(profile);
+ IInstallableUnit[] toInstallArray = new IInstallableUnit[] {toInstallIU};
request.addInstallableUnits(toInstallArray);
+
+ // Provision
+ IDirector director = createDirector();
IStatus result = director.provision(request, null, null);
- if (!result.isOK())
+ if (!result.isOK()) {
LogHelper.log(result);
- assertTrue("1.0", result.isOK());
+ }
+
+ assertTrue(result.isOK());
assertProfileContains("1.1", profile, allUnits);
}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/engine/PhaseSetTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/engine/PhaseSetTest.java
index f085f9415..609d1d69a 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/engine/PhaseSetTest.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/engine/PhaseSetTest.java
@@ -12,21 +12,42 @@ package org.eclipse.equinox.p2.tests.engine;
import java.io.File;
import java.net.URI;
-import java.util.*;
+import java.util.EventObject;
+import java.util.HashMap;
+import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
-import org.eclipse.equinox.internal.p2.engine.*;
+import org.eclipse.equinox.internal.p2.engine.BeginOperationEvent;
+import org.eclipse.equinox.internal.p2.engine.CommitOperationEvent;
+import org.eclipse.equinox.internal.p2.engine.EngineSession;
+import org.eclipse.equinox.internal.p2.engine.InstallableUnitOperand;
+import org.eclipse.equinox.internal.p2.engine.Phase;
+import org.eclipse.equinox.internal.p2.engine.PhaseEvent;
+import org.eclipse.equinox.internal.p2.engine.PhaseSet;
+import org.eclipse.equinox.internal.p2.engine.ProfileEvent;
+import org.eclipse.equinox.internal.p2.engine.RollbackOperationEvent;
import org.eclipse.equinox.internal.p2.repository.DownloadProgressEvent;
import org.eclipse.equinox.internal.p2.touchpoint.natives.Util;
import org.eclipse.equinox.internal.provisional.p2.core.eventbus.ProvisioningListener;
import org.eclipse.equinox.internal.provisional.p2.repository.RepositoryEvent;
import org.eclipse.equinox.p2.core.ProvisionException;
-import org.eclipse.equinox.p2.engine.*;
+import org.eclipse.equinox.p2.engine.IEngine;
+import org.eclipse.equinox.p2.engine.IPhaseSet;
+import org.eclipse.equinox.p2.engine.IProfile;
+import org.eclipse.equinox.p2.engine.IProvisioningPlan;
+import org.eclipse.equinox.p2.engine.PhaseSetFactory;
+import org.eclipse.equinox.p2.engine.ProvisioningContext;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
-import org.eclipse.equinox.p2.query.*;
+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.p2.repository.artifact.IArtifactRepository;
import org.eclipse.equinox.p2.tests.AbstractProvisioningTest;
import org.eclipse.equinox.p2.tests.TestActivator;
@@ -176,7 +197,7 @@ public class PhaseSetTest extends AbstractProvisioningTest {
getArtifactRepositoryManager().loadRepository(repoURI, null);
doProvisioning(repoURI, phaseSet, query, expectedCode, monitor);
// make sure the listener handles all event already that are dispatched asynchronously
- listener.latch.await(10, TimeUnit.SECONDS);
+ listener.latch.await(15, TimeUnit.SECONDS);
assertFalse("Engine still do provisioning after pausing.", listener.hasProvisioningEventAfterPaused);
pauseJob.join();
} finally {
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/RequirementToString.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/RequirementToString.java
index 1ccc188bf..476d0daed 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/RequirementToString.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/RequirementToString.java
@@ -23,18 +23,23 @@ import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
public class RequirementToString extends TestCase {
public void testRequirementWithEmptyRange() {
IRequirement req = MetadataFactory.createRequirement("expectedNameSpace", "expectedName", VersionRange.emptyRange, null, false, false);
- assertEquals("expectedNameSpace expectedName 0.0.0", req.toString());
+ assertEquals("expectedNameSpace; expectedName 0.0.0", req.toString());
}
public void testStandardRequirement() {
IRequirement req = MetadataFactory.createRequirement("expectedNameSpace", "expectedName", new VersionRange("[1.0.0, 2.0.0)"), null, false, false);
- assertEquals("expectedNameSpace expectedName [1.0.0,2.0.0)", req.toString());
+ assertEquals("expectedNameSpace; expectedName [1.0.0,2.0.0)", req.toString());
+ }
+
+ public void testPropertiesRequirement() {
+ IRequirement req = MetadataFactory.createRequirement("expectedNameSpace", "(key=val)", null, 1, 1, true);
+ assertEquals("expectedNameSpace; (key=val)", req.toString());
}
public void testFancyRequirement() {
- Object[] expressionParameters = new Object[] {"expectedId1, expectedVersion1", "expectedId2, expectedVersion2"};
+ Object[] expressionParameters = new Object[] {"expectedId1", "expectedVersion1", "expectedId2", "expectedVersion2"};
IMatchExpression<IInstallableUnit> iuMatcher = ExpressionUtil.getFactory().<IInstallableUnit> matchExpression(ExpressionUtil.parse("(id == $0 && version == $1) || (id == $2 && version == $3)"), expressionParameters);
IRequirement req = MetadataFactory.createRequirement(iuMatcher, null, 1, 1, true);
- assertEquals("id == $0 && version == $1 || id == $2 && version == $3 expectedId1, expectedVersion1 expectedId2, expectedVersion2", req.toString().trim());
+ assertEquals("id == $0 && version == $1 || id == $2 && version == $3 (expectedId1, expectedVersion1, expectedId2, expectedVersion2)", req.toString().trim());
}
}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/expression/AllTests.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/expression/AllTests.java
index 27ebc00b8..8e5be56d7 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/expression/AllTests.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/expression/AllTests.java
@@ -4,13 +4,16 @@
* 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:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.equinox.p2.tests.metadata.expression;
-import junit.framework.*;
+import junit.framework.JUnit4TestAdapter;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
/**
* Performs all automated director tests.
@@ -20,7 +23,7 @@ public class AllTests extends TestCase {
public static Test suite() {
TestSuite suite = new TestSuite(AllTests.class.getName());
suite.addTestSuite(ExpressionTest.class);
- suite.addTestSuite(FilterTest.class);
+ suite.addTest(new JUnit4TestAdapter(FilterTest.class));
return suite;
}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/expression/FilterTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/expression/FilterTest.java
index 0d6895ac2..4a51833fb 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/expression/FilterTest.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/expression/FilterTest.java
@@ -10,19 +10,225 @@
*******************************************************************************/
package org.eclipse.equinox.p2.tests.metadata.expression;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
import java.math.BigDecimal;
import java.math.BigInteger;
-import java.util.*;
-import junit.framework.*;
-import org.eclipse.equinox.p2.metadata.expression.*;
-import org.osgi.framework.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import org.eclipse.equinox.p2.metadata.Version;
+import org.eclipse.equinox.p2.metadata.expression.ExpressionParseException;
+import org.eclipse.equinox.p2.metadata.expression.ExpressionUtil;
+import org.eclipse.equinox.p2.metadata.expression.IFilterExpression;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Filter;
+import org.osgi.framework.ServiceReference;
+
+public class FilterTest {
+ @Test
+ public void testComparable() throws Exception {
+ IFilterExpression f1 = ExpressionUtil.parseLDAP("(comparable=42)");
+ Object comp;
+ Map<String, Object> hash = new HashMap<>();
+
+ comp = new SampleComparable("42");
+ hash.put("comparable", comp);
+ assertTrue("does not match filter", f1.match(hash));
+ assertTrue("does not match filter", f1.match(new DictionaryServiceReference(hash)));
+
+ comp = Long.valueOf(42);
+ hash.put("comparable", comp);
+ assertTrue("does not match filter", f1.match(hash));
+ assertTrue("does not match filter", f1.match(new DictionaryServiceReference(hash)));
+
+ IFilterExpression f2 = ExpressionUtil.parseLDAP("(comparable=42)");
+ hash = new Hashtable<>();
+
+ comp = new SampleComparable("42");
+ hash.put("comparable", comp);
+ assertTrue("does not match filter", f2.match(hash));
+ assertTrue("does not match filter", f2.match(new DictionaryServiceReference(hash)));
+
+ comp = Long.valueOf(42);
+ hash.put("comparable", comp);
+ assertTrue("does not match filter", f2.match(hash));
+ assertTrue("does not match filter", f2.match(new DictionaryServiceReference(hash)));
+
+ assertEquals("not equal", f1, f2);
+ }
+
+ @Test
+ public void testFilterEquality() {
+ Filter f1 = ExpressionUtil.parseLDAP("( a = bedroom )");
+ Filter f2 = ExpressionUtil.parseLDAP(" (a= bedroom ) ");
+ assertEquals("not equal", "(a= bedroom )", f1.toString());
+ assertEquals("not equal", "(a= bedroom )", f2.toString());
+ assertEquals("not equal", f1, f2);
+ assertEquals("not equal", f2, f1);
+ assertEquals("not equal", f1.hashCode(), f2.hashCode());
+
+ f1 = ExpressionUtil.parseLDAP("(status =\\28o*\\5c\\29\\2a)");
+ assertEquals("not equal", "(status=\\28o*\\5c\\29\\2a)", f1.toString());
+
+ f1 = ExpressionUtil.parseLDAP("(|(a=1)(&(a=1)(b=1)))");
+ f2 = ExpressionUtil.parseLDAP("(a=1)");
+
+ f1 = ExpressionUtil.parseLDAP("(|(&(os=macos)(ws=cocoa)(arch=x86))(&(ws=cocoa)(os=macos)(arch=ppc)))");
+ f2 = ExpressionUtil.parseLDAP("(&(os=macos)(ws=cocoa)(|(arch=x86)(arch=ppc)))");
+ assertEquals("not equal: f1:" + f1.toString() + ", f2:" + f1.toString(), f1, f2);
+
+ f1 = ExpressionUtil.parseLDAP("(&(|(x=a)(y=b)(z=a))(|(x=a)(y=b)(z=b)))");
+ f2 = ExpressionUtil.parseLDAP("(|(x=a)(y=b)(&(z=a)(z=b)))");
+ assertEquals("not equal: f1:" + f1.toString() + ", f2:" + f1.toString(), f1, f2);
+
+ f1 = ExpressionUtil.parseLDAP("(&(a=1)(|(a=1)(b=1)))");
+ f2 = ExpressionUtil.parseLDAP("(a=1)");
+
+ f1 = ExpressionUtil.parseLDAP("(|(a=1)(&(a=1)(b=1)))");
+ f2 = ExpressionUtil.parseLDAP("(a=1)");
+ assertEquals("not equal: f1:" + f1.toString() + ", f2:" + f1.toString(), f1, f2);
+ }
+
+ @Test
+ public void testFilterMatching() {
+ Dictionary<String, Object> props = new Hashtable<>();
+ props.put("room", "bedroom");
+ props.put("channel", Integer.valueOf(34));
+ props.put("status", "(on\\)*");
+ props.put("max record time", Long.valueOf(150));
+ props.put("canrecord", "true(x)");
+ props.put("shortvalue", Short.valueOf((short) 1000));
+ props.put("bytevalue", Byte.valueOf((byte) 10));
+ props.put("floatvalue", Float.valueOf(1.01f));
+ props.put("doublevalue", Double.valueOf(2.01));
+ props.put("charvalue", Character.valueOf('A'));
+ props.put("booleanvalue", Boolean.FALSE);
+ props.put("listvalue", Arrays.asList(1, 2, 3));
+ props.put("versionlistvalue", Arrays.asList(Version.create("1"), Version.create("2"), Version.create("3")));
+ props.put("weirdvalue", new Hashtable<>());
+ props.put("bigintvalue", new BigInteger("4123456"));
+ props.put("bigdecvalue", new BigDecimal("4.123456"));
+
+ assertMatch("(room=*)", props);
+ assertNoMatch("(rooom=*)", props);
+ assertMatch("(room=bedroom)", props);
+ assertMatch("(room~= B E D R O O M )", props);
+ assertNoMatch("(room=abc)", props);
+ assertMatch(" ( room >=aaaa)", props);
+ assertNoMatch("(room <=aaaa)", props);
+ assertMatch(" ( room =b*) ", props);
+ assertMatch(" ( room =*m) ", props);
+ assertMatch("(room=bed*room)", props);
+ assertMatch(" ( room =b*oo*m) ", props);
+ assertMatch(" ( room =*b*oo*m*) ", props);
+ assertNoMatch(" ( room =b*b* *m*) ", props);
+ assertMatch(" (& (room =bedroom) (channel = 34))", props);
+ assertNoMatch(" (& (room =b*) (room =*x) (channel=34))", props);
+ assertMatch("(| (room =bed*)(channel=222)) ", props);
+ assertMatch("(| (room =boom*)(channel=34)) ", props);
+ assertMatch(" (! (room =ab*b*oo*m*) ) ", props);
+ assertMatch(" (status =\\(o*\\\\\\)\\*) ", props);
+ assertMatch(" (status =\\28o*\\5c\\29\\2a) ", props);
+ assertMatch(" (status =\\28o*\\5C\\29\\2A) ", props);
+ assertMatch(" (canRecord =true\\(x\\)) ", props);
+ assertMatch("(max Record Time <=150) ", props);
+ assertMatch("(shortValue >= 100) ", props);
+ assertMatch(" ( & ( byteValue <= 100 ) ( byteValue >= 10 ) ) ", props);
+ assertMatch("(bigIntValue = 4123456) ", props);
+ assertMatch("(bigDecValue = 4.123456) ", props);
+ assertMatch("(floatValue >= 1.0) ", props);
+ assertMatch("(doubleValue <= 2.011) ", props);
+ assertMatch("(charValue ~= a) ", props);
+ assertMatch("(booleanValue = false) ", props);
+ assertMatch("(listvalue>=0)", props);
+ assertMatch("(listvalue=3)", props);
+ assertMatch("(!(listvalue>=4))", props);
+ assertMatch("(versionlistvalue>=0)", props);
+ assertMatch("(versionlistvalue=3)", props);
+ assertMatch("(!(versionlistvalue>=4))", props);
+ assertMatch("(& (| (room =d*m) (room =bed*) (room=abc)) (! (channel=999)))", props);
+ assertNoMatch("(room=bedroom)", null);
+ assertNoMatch("(weirdValue = 100) ", props);
+ }
+
+ @Test
+ public void testFilterParserErrors() {
+ assertParseError("()");
+ assertParseError("(=foo)");
+ assertParseError("(");
+ assertParseError("(abc = ))");
+ assertParseError("(& (abc = xyz) (& (345))");
+ assertParseError(" (room = b**oo!*m*) ) ");
+ assertParseError(" (room = b**oo)*m*) ) ");
+ assertParseError(" (room = *=b**oo*m*) ) ");
+ assertParseError(" (room = =b**oo*m*) ) ");
+ }
+
+ private void assertMatch(String query, Dictionary<String, Object> props) {
+ expectMatch(query, props, true);
+ }
+
+ private void assertNoMatch(String query, Dictionary<String, Object> props) {
+ expectMatch(query, props, false);
+ }
+
+ private void expectMatch(String query, Dictionary<String, Object> props, boolean match) {
+ Filter f = ExpressionUtil.parseLDAP(query);
+
+ // TODO Doing raw conversion here for simplicity; could convert to Dictionary<String, ?>
+ // but the filter impl must still handle cases where non String keys are used.
+ assertEquals(match, f.match(props));
+
+ ServiceReference ref = new DictionaryServiceReference((Map<String, ? extends Object>) props);
+ assertEquals(match, f.match(ref));
+ }
+
+ private void assertParseError(String query) {
+ try {
+ ExpressionUtil.parseLDAP(query);
+ fail("expected exception");
+ } catch (ExpressionParseException e) {
+ // Pass
+ }
+ }
+
+ private static class SampleComparable implements Comparable<SampleComparable> {
+ private int value = -1;
+
+ public SampleComparable(String value) {
+ this.value = Integer.parseInt(value);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof SampleComparable && value == ((SampleComparable) o).value;
+ }
+
+ @Override
+ public int compareTo(SampleComparable o) {
+ return value - o.value;
+ }
+
+ @Override
+ public String toString() {
+ return String.valueOf(value);
+ }
+ }
-public class FilterTest extends TestCase {
private static class DictionaryServiceReference implements ServiceReference {
private final Map<String, ? extends Object> dictionary;
-
+
private final String[] keys;
-
+
DictionaryServiceReference(Map<String, ? extends Object> dictionary) {
if (dictionary == null) {
this.dictionary = null;
@@ -42,17 +248,17 @@ public class FilterTest extends TestCase {
}
this.keys = keyList.toArray(new String[keyList.size()]);
}
-
+
@Override
public int compareTo(Object reference) {
throw new UnsupportedOperationException();
}
-
+
@Override
public Bundle getBundle() {
return null;
}
-
+
@Override
public Object getProperty(String k) {
for (int i = 0, length = keys.length; i < length; i++) {
@@ -63,230 +269,25 @@ public class FilterTest extends TestCase {
}
return null;
}
-
+
@Override
public String[] getPropertyKeys() {
return keys.clone();
}
-
+
@Override
public Bundle[] getUsingBundles() {
throw new UnsupportedOperationException();
}
-
+
@Override
public boolean isAssignableTo(Bundle bundle, String className) {
throw new UnsupportedOperationException();
}
-
+
@Override
public Dictionary<String, Object> getProperties() {
return new Hashtable<>(dictionary);
}
}
-
- private static class SampleComparable implements Comparable<SampleComparable> {
- private int value = -1;
-
- public SampleComparable(String value) {
- this.value = Integer.parseInt(value);
- }
-
- @Override
- public boolean equals(Object o) {
- return o instanceof SampleComparable && value == ((SampleComparable) o).value;
- }
-
- @Override
- public int compareTo(SampleComparable o) {
- return value - o.value;
- }
-
- @Override
- public String toString() {
- return String.valueOf(value);
- }
- }
-
- static final int ISTRUE = 1;
-
- static final int ISFALSE = 2;
-
- static final int ISILLEGAL = 3;
-
- public static Test suite() {
- return new TestSuite(FilterTest.class);
- }
-
- public void testComparable() throws Exception {
- IFilterExpression f1 = ExpressionUtil.parseLDAP("(comparable=42)"); //$NON-NLS-1$
- Object comp;
- Map<String, Object> hash = new HashMap<>();
-
- comp = new SampleComparable("42"); //$NON-NLS-1$
- hash.put("comparable", comp); //$NON-NLS-1$
- assertTrue("does not match filter", f1.match(hash)); //$NON-NLS-1$
- assertTrue("does not match filter", f1.match(new DictionaryServiceReference(hash))); //$NON-NLS-1$
-
- comp = Long.valueOf(42);
- hash.put("comparable", comp); //$NON-NLS-1$
- assertTrue("does not match filter", f1.match(hash)); //$NON-NLS-1$
- assertTrue("does not match filter", f1.match(new DictionaryServiceReference(hash))); //$NON-NLS-1$
-
- IFilterExpression f2 = ExpressionUtil.parseLDAP("(comparable=42)"); //$NON-NLS-1$
- hash = new Hashtable<>();
-
- comp = new SampleComparable("42"); //$NON-NLS-1$
- hash.put("comparable", comp); //$NON-NLS-1$
- assertTrue("does not match filter", f2.match(hash)); //$NON-NLS-1$
- assertTrue("does not match filter", f2.match(new DictionaryServiceReference(hash))); //$NON-NLS-1$
-
- comp = Long.valueOf(42);
- hash.put("comparable", comp); //$NON-NLS-1$
- assertTrue("does not match filter", f2.match(hash)); //$NON-NLS-1$
- assertTrue("does not match filter", f2.match(new DictionaryServiceReference(hash))); //$NON-NLS-1$
-
- assertEquals("not equal", f1, f2); //$NON-NLS-1$
- }
-
- public void testFilter() {
- Dictionary<String, Object> props = new Hashtable<>();
- props.put("room", "bedroom"); //$NON-NLS-1$ //$NON-NLS-2$
- props.put("channel", Integer.valueOf(34)); //$NON-NLS-1$
- props.put("status", "(on\\)*"); //$NON-NLS-1$//$NON-NLS-2$
- props.put("max record time", Long.valueOf(150)); //$NON-NLS-1$
- props.put("canrecord", "true(x)"); //$NON-NLS-1$ //$NON-NLS-2$
- props.put("shortvalue", Short.valueOf((short) 1000)); //$NON-NLS-1$
- props.put("bytevalue", Byte.valueOf((byte) 10)); //$NON-NLS-1$
- props.put("floatvalue", Float.valueOf(1.01f)); //$NON-NLS-1$
- props.put("doublevalue", Double.valueOf(2.01)); //$NON-NLS-1$
- props.put("charvalue", Character.valueOf('A')); //$NON-NLS-1$
- props.put("booleanvalue", Boolean.FALSE); //$NON-NLS-1$
- props.put("weirdvalue", new Hashtable<>()); //$NON-NLS-1$
- try {
- props.put("bigintvalue", new BigInteger("4123456")); //$NON-NLS-1$ //$NON-NLS-2$
- } catch (NoClassDefFoundError e) {
- // ignore
- }
- try {
- props.put("bigdecvalue", new BigDecimal("4.123456")); //$NON-NLS-1$ //$NON-NLS-2$
- } catch (NoClassDefFoundError e) {
- // ignore
- }
-
- testFilter("(room=*)", props, ISTRUE); //$NON-NLS-1$
- testFilter("(rooom=*)", props, ISFALSE); //$NON-NLS-1$
- testFilter("(room=bedroom)", props, ISTRUE); //$NON-NLS-1$
- testFilter("(room~= B E D R O O M )", props, ISTRUE); //$NON-NLS-1$
- testFilter("(room=abc)", props, ISFALSE); //$NON-NLS-1$
- testFilter(" ( room >=aaaa)", props, ISTRUE); //$NON-NLS-1$
- testFilter("(room <=aaaa)", props, ISFALSE); //$NON-NLS-1$
- testFilter(" ( room =b*) ", props, ISTRUE); //$NON-NLS-1$
- testFilter(" ( room =*m) ", props, ISTRUE); //$NON-NLS-1$
- testFilter("(room=bed*room)", props, ISTRUE); //$NON-NLS-1$
- testFilter(" ( room =b*oo*m) ", props, ISTRUE); //$NON-NLS-1$
- testFilter(" ( room =*b*oo*m*) ", props, ISTRUE); //$NON-NLS-1$
- testFilter(" ( room =b*b* *m*) ", props, ISFALSE); //$NON-NLS-1$
- testFilter(" (& (room =bedroom) (channel = 34))", props, ISTRUE); //$NON-NLS-1$
- testFilter(" (& (room =b*) (room =*x) (channel=34))", props, ISFALSE); //$NON-NLS-1$
- testFilter("(| (room =bed*)(channel=222)) ", props, ISTRUE); //$NON-NLS-1$
- testFilter("(| (room =boom*)(channel=34)) ", props, ISTRUE); //$NON-NLS-1$
- testFilter(" (! (room =ab*b*oo*m*) ) ", props, ISTRUE); //$NON-NLS-1$
- testFilter(" (status =\\(o*\\\\\\)\\*) ", props, ISTRUE); //$NON-NLS-1$
- testFilter(" (status =\\28o*\\5c\\29\\2a) ", props, ISTRUE); //$NON-NLS-1$
- testFilter(" (status =\\28o*\\5C\\29\\2A) ", props, ISTRUE); //$NON-NLS-1$
- testFilter(" (canRecord =true\\(x\\)) ", props, ISTRUE); //$NON-NLS-1$
- testFilter("(max Record Time <=150) ", props, ISTRUE); //$NON-NLS-1$
- testFilter("(shortValue >= 100) ", props, ISTRUE); //$NON-NLS-1$
- testFilter(" ( & ( byteValue <= 100 ) ( byteValue >= 10 ) ) ", props, ISTRUE); //$NON-NLS-1$
- testFilter("(bigIntValue = 4123456) ", props, ISTRUE); //$NON-NLS-1$
- testFilter("(bigDecValue = 4.123456) ", props, ISTRUE); //$NON-NLS-1$
- testFilter("(floatValue >= 1.0) ", props, ISTRUE); //$NON-NLS-1$
- testFilter("(doubleValue <= 2.011) ", props, ISTRUE); //$NON-NLS-1$
- testFilter("(charValue ~= a) ", props, ISTRUE); //$NON-NLS-1$
- testFilter("(booleanValue = false) ", props, ISTRUE); //$NON-NLS-1$
- testFilter("(& (| (room =d*m) (room =bed*) (room=abc)) (! (channel=999)))", props, ISTRUE); //$NON-NLS-1$
- testFilter("(room=bedroom)", null, ISFALSE); //$NON-NLS-1$
-
- testFilter("()", props, ISILLEGAL); //$NON-NLS-1$
- testFilter("(=foo)", props, ISILLEGAL); //$NON-NLS-1$
- testFilter("(", props, ISILLEGAL); //$NON-NLS-1$
- testFilter("(abc = ))", props, ISILLEGAL); //$NON-NLS-1$
- testFilter("(& (abc = xyz) (& (345))", props, ISILLEGAL); //$NON-NLS-1$
- testFilter(" (room = b**oo!*m*) ) ", props, ISILLEGAL); //$NON-NLS-1$
- testFilter(" (room = b**oo)*m*) ) ", props, ISILLEGAL); //$NON-NLS-1$
- testFilter(" (room = *=b**oo*m*) ) ", props, ISILLEGAL); //$NON-NLS-1$
- testFilter(" (room = =b**oo*m*) ) ", props, ISILLEGAL); //$NON-NLS-1$
-
- try {
- Filter f1 = ExpressionUtil.parseLDAP("( a = bedroom )"); //$NON-NLS-1$
- Filter f2 = ExpressionUtil.parseLDAP(" (a= bedroom ) "); //$NON-NLS-1$
- assertEquals("not equal", "(a= bedroom )", f1.toString()); //$NON-NLS-1$ //$NON-NLS-2$
- assertEquals("not equal", "(a= bedroom )", f2.toString()); //$NON-NLS-1$ //$NON-NLS-2$
- assertEquals("not equal", f1, f2); //$NON-NLS-1$
- assertEquals("not equal", f2, f1); //$NON-NLS-1$
- assertEquals("not equal", f1.hashCode(), f2.hashCode()); //$NON-NLS-1$
-
- f1 = ExpressionUtil.parseLDAP("(status =\\28o*\\5c\\29\\2a)");
- assertEquals("not equal", "(status=\\28o*\\5c\\29\\2a)", f1.toString()); //$NON-NLS-1$ //$NON-NLS-2$
-
- f1 = ExpressionUtil.parseLDAP("(|(a=1)(&(a=1)(b=1)))"); //$NON-NLS-1$
- f2 = ExpressionUtil.parseLDAP("(a=1)"); //$NON-NLS-1$
- System.out.println(f2.toString());
- System.out.println(f1.toString());
-
- f1 = ExpressionUtil.parseLDAP("(|(&(os=macos)(ws=cocoa)(arch=x86))(&(ws=cocoa)(os=macos)(arch=ppc)))"); //$NON-NLS-1$
- f2 = ExpressionUtil.parseLDAP("(&(os=macos)(ws=cocoa)(|(arch=x86)(arch=ppc)))"); //$NON-NLS-1$
- System.out.println(f2.toString());
- System.out.println(f1.toString());
- assertEquals("not equal", f1, f2); //$NON-NLS-1$
-
- f1 = ExpressionUtil.parseLDAP("(&(|(x=a)(y=b)(z=a))(|(x=a)(y=b)(z=b)))"); //$NON-NLS-1$
- f2 = ExpressionUtil.parseLDAP("(|(x=a)(y=b)(&(z=a)(z=b)))"); //$NON-NLS-1$
- System.out.println(f2.toString());
- System.out.println(f1.toString());
- assertEquals("not equal", f1, f2); //$NON-NLS-1$
-
- f1 = ExpressionUtil.parseLDAP("(&(a=1)(|(a=1)(b=1)))"); //$NON-NLS-1$
- f2 = ExpressionUtil.parseLDAP("(a=1)"); //$NON-NLS-1$
- System.out.println(f2.toString());
- System.out.println(f1.toString());
-
- f1 = ExpressionUtil.parseLDAP("(|(a=1)(&(a=1)(b=1)))"); //$NON-NLS-1$
- f2 = ExpressionUtil.parseLDAP("(a=1)"); //$NON-NLS-1$
- System.out.println(f2.toString());
- System.out.println(f1.toString());
- assertEquals("not equal", f1, f2); //$NON-NLS-1$
- } catch (IllegalArgumentException e) {
- fail("unexpected invalid syntax: " + e); //$NON-NLS-1$
- }
- testFilter("(weirdValue = 100) ", props, ISFALSE); //$NON-NLS-1$
-
- }
-
- private void testFilter(String query, Dictionary<String, Object> props, int expect) {
- final ServiceReference ref = new DictionaryServiceReference((Map<String, ? extends Object>) props);
- Filter f1;
- try {
- f1 = ExpressionUtil.parseLDAP(query);
-
- if (expect == ISILLEGAL) {
- fail("expected exception"); //$NON-NLS-1$
- }
- } catch (ExpressionParseException e) {
- System.out.println(e.toString());
- if (expect != ISILLEGAL) {
- fail("exception: " + e.toString()); //$NON-NLS-1$
- }
- return;
- }
-
- // TODO Doing raw conversion here for simplicity; could convert to Dictionary<String, ?>
- // but the filter impl must still handle cases where non String keys are used.
- boolean val = f1.match(props);
- assertEquals("wrong result", expect == ISTRUE, val); //$NON-NLS-1$
-
- val = f1.match(ref);
- assertEquals("wrong result", expect == ISTRUE, val); //$NON-NLS-1$
- }
}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/repository/SPIMetadataRepositoryTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/repository/SPIMetadataRepositoryTest.java
index 022b6549f..605143491 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/repository/SPIMetadataRepositoryTest.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/repository/SPIMetadataRepositoryTest.java
@@ -179,14 +179,14 @@ public class SPIMetadataRepositoryTest extends AbstractProvisioningTest {
class SPIProvidedCapability implements IProvidedCapability {
private final String namespace;
- private final Map<String, Object> attributes;
+ private final Map<String, Object> properties;
public SPIProvidedCapability(String namespace, String name, Version version) {
this.namespace = namespace;
- this.attributes = new HashMap<>();
- attributes.put(namespace, name);
- attributes.put(ProvidedCapability.ATTRIBUTE_VERSION, version);
+ this.properties = new HashMap<>();
+ properties.put(namespace, name);
+ properties.put(IProvidedCapability.PROPERTY_VERSION, version);
}
@Override
@@ -199,7 +199,7 @@ public class SPIMetadataRepositoryTest extends AbstractProvisioningTest {
if (!(namespace.equals(otherCapability.getNamespace()))) {
return false;
}
- if (!(attributes.equals(otherCapability.getAttributes()))) {
+ if (!(properties.equals(otherCapability.getProperties()))) {
return false;
}
return true;
@@ -207,12 +207,12 @@ public class SPIMetadataRepositoryTest extends AbstractProvisioningTest {
@Override
public String toString() {
- return namespace + "; " + attributes;
+ return namespace + "; " + properties;
}
@Override
public String getName() {
- return (String) attributes.get(namespace);
+ return (String) properties.get(namespace);
}
@Override
@@ -222,12 +222,12 @@ public class SPIMetadataRepositoryTest extends AbstractProvisioningTest {
@Override
public Version getVersion() {
- return (Version) attributes.get(ProvidedCapability.ATTRIBUTE_VERSION);
+ return (Version) properties.get(IProvidedCapability.PROPERTY_VERSION);
}
@Override
- public Map<String, Object> getAttributes() {
- return Collections.unmodifiableMap(attributes);
+ public Map<String, Object> getProperties() {
+ return Collections.unmodifiableMap(properties);
}
}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/PropertyMatchRequirement.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/PropertyMatchRequirement.java
new file mode 100644
index 000000000..4d709c93a
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/PropertyMatchRequirement.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2017 IBM Corporation 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: IBM Corporation - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.p2.tests.planner;
+
+import static org.eclipse.core.runtime.IStatus.ERROR;
+import static org.eclipse.core.runtime.IStatus.OK;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.eclipse.equinox.internal.p2.director.Explanation.MissingIU;
+import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
+import org.eclipse.equinox.internal.provisional.p2.director.PlannerStatus;
+import org.eclipse.equinox.internal.provisional.p2.director.RequestStatus;
+import org.eclipse.equinox.p2.engine.IProfile;
+import org.eclipse.equinox.p2.engine.IProvisioningPlan;
+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.planner.IPlanner;
+import org.eclipse.equinox.p2.tests.AbstractProvisioningTest;
+
+public class PropertyMatchRequirement extends AbstractProvisioningTest {
+ private IInstallableUnit providerIu;
+ private IInstallableUnit consumerIu;
+
+ private IProfile profile;
+ private IPlanner planner;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ // A standard OSGi service representation
+ String osgiService = "osgi.service";
+ String objectClass = "objectClass";
+ List<String> objectClassList = Arrays.asList("org.example.A", "org.example.B", "org.example.C");
+
+ // Provider.
+ // TODO Check if p2 really needs a name. IProvidedCapability.equals() can differentiate by properties only.
+ Map<String, Object> capability = new HashMap<>();
+ capability.put(osgiService, "ignored-1");
+ capability.put(objectClass, objectClassList);
+
+ IProvidedCapability[] provides = new IProvidedCapability[] {
+ MetadataFactory.createProvidedCapability(osgiService, capability)
+ };
+ providerIu = createIU("provider", DEFAULT_VERSION, provides);
+
+ // Consumer
+ String requirement = String.format("(%s=%s)", objectClass, objectClassList.get(0));
+ IRequirement[] requires = new IRequirement[] {
+ MetadataFactory.createRequirement(osgiService, requirement, null, 1, 1, true)
+ };
+ consumerIu = createIU("consumer", DEFAULT_VERSION, requires);
+
+ // Planner
+ profile = createProfile("test." + getName());
+ planner = createPlanner();
+ }
+
+ public void testMandatoryPresent() {
+ createTestMetdataRepository(new IInstallableUnit[] {providerIu, consumerIu});
+
+ ProfileChangeRequest req = new ProfileChangeRequest(profile);
+ req.add(consumerIu);
+
+ // Must pass
+ IProvisioningPlan plan = planner.getProvisioningPlan(req, null, null);
+ assertEquals(OK, plan.getStatus().getSeverity());
+
+ // And both consumer and provider must be installed
+ assertInstallOperand(plan, consumerIu);
+ assertInstallOperand(plan, providerIu);
+ }
+
+ public void testMandatoryAbsent() {
+ createTestMetdataRepository(new IInstallableUnit[] {consumerIu});
+
+ ProfileChangeRequest req = new ProfileChangeRequest(profile);
+ req.add(consumerIu);
+
+ // Must fail
+ IProvisioningPlan plan = planner.getProvisioningPlan(req, null, null);
+ assertEquals(ERROR, plan.getStatus().getSeverity());
+
+ // With a good explanation
+ RequestStatus requestStatus = ((PlannerStatus) plan.getStatus()).getRequestStatus();
+ IRequirement consumerReq = consumerIu.getRequirements().iterator().next();
+ requestStatus.getExplanations()
+ .stream()
+ .filter(e -> e instanceof MissingIU)
+ .filter(e -> (((MissingIU) e).req.toString()).equals(consumerReq.toString()))
+ .findFirst()
+ .orElseGet(() -> {
+ fail("Did not find explanation for missing requirement: " + consumerReq);
+ return null;
+ });
+
+ // And the consumer must not be installed
+ assertNoOperand(plan, consumerIu);
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/ActionTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/ActionTest.java
index 058cca76c..faf51598b 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/ActionTest.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/actions/ActionTest.java
@@ -27,15 +27,13 @@ import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.equinox.internal.p2.core.helpers.FileUtils;
+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.Version;
import org.eclipse.equinox.p2.metadata.VersionRange;
-import org.eclipse.equinox.p2.metadata.expression.ExpressionUtil;
-import org.eclipse.equinox.p2.metadata.expression.IExpression;
-import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
import org.eclipse.equinox.p2.publisher.AbstractPublisherAction;
import org.eclipse.equinox.p2.publisher.IPublisherInfo;
import org.eclipse.equinox.p2.publisher.IPublisherResult;
@@ -92,18 +90,25 @@ public abstract class ActionTest extends AbstractProvisioningTest {
verifyRequirement(actual, namespace, name, range, null, 1, 1, true);
}
- protected void verifyRequirement(Collection<IRequirement> actual, String namespace, String name, VersionRange range, String filterStr, int minCard, int maxCard, boolean greedy) {
- IRequirement expected = MetadataFactory.createRequirement(namespace, name, range, null, minCard, maxCard, greedy);
+ protected void verifyRequirement(Collection<IRequirement> actual, String namespace, String name, VersionRange range, String envFilter, int minCard, int maxCard, boolean greedy) {
+ IRequirement expected = MetadataFactory.createRequirement(namespace, name, range, InstallableUnit.parseFilter(envFilter), minCard, maxCard, greedy);
verifyRequirement(actual, expected);
}
- protected void verifyRequirement(Collection<IRequirement> actual, String matchExpr, int minCard, int maxCard, boolean greedy) {
- IExpression expr = ExpressionUtil.parse(matchExpr);
- IMatchExpression<IInstallableUnit> matcher = ExpressionUtil.getFactory().matchExpression(expr);
- IRequirement expected = MetadataFactory.createRequirement(matcher, null, minCard, maxCard, greedy);
+ protected void verifyRequirement(Collection<IRequirement> actual, String namespace, String propsFilter, String envFilter, int minCard, int maxCard, boolean greedy) {
+ IRequirement expected = MetadataFactory.createRequirement(namespace, propsFilter, InstallableUnit.parseFilter(envFilter), minCard, maxCard, greedy);
verifyRequirement(actual, expected);
}
+ /**
+ * Safe to use only if actual and expected were created by the same method of {@link MetadataFactory}
+ * because match expressions are not safe to compare for equality.
+ *
+ * This must be guaranteed by all sub-class test cases
+ *
+ * @param actual
+ * @param expected
+ */
protected void verifyRequirement(Collection<IRequirement> actual, IRequirement expected) {
for (IRequirement act : actual) {
if (expected.getMatches().equals(act.getMatches())) {
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 af99bfe42..7e3ab0344 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
@@ -77,18 +77,19 @@ import org.eclipse.equinox.spi.p2.publisher.PublisherHelper;
public class BundlesActionTest extends ActionTest {
private static final String OSGI = PublisherHelper.OSGI_BUNDLE_CLASSIFIER;
private static final String OSGI_IDENTITY = "osgi.identity";
+ private static final String OSGI_EE = "osgi.ee";
private static final String JAVA_PACKAGE = "java.package";//$NON-NLS-1$
- private static final String JAVA_EE_1_4_REQ = "providedCapabilities.exists(pc | pc.namespace == 'osgi.ee' && pc.attributes ~= filter('(|(&(osgi.ee=JavaSE)(version=1.4))(&(osgi.ee=CDC/Foundation)(version=1.1)))'))";
- private static final String JAVA_EE_1_6_REQ = "providedCapabilities.exists(pc | pc.namespace == 'osgi.ee' && pc.attributes ~= filter('(&(osgi.ee=JavaSE)(version=1.6))'))";
+ private static final String JAVA_EE_1_4 = "(|(&(osgi.ee=JavaSE)(version=1.4))(&(osgi.ee=CDC/Foundation)(version=1.1)))";
+ private static final String JAVA_EE_1_6 = "(&(osgi.ee=JavaSE)(version=1.6))";
private static final String TEST1_IUD_NAME = "iud";//$NON-NLS-1$
private static final String TEST1_PROVZ_NAME = "iuz";//$NON-NLS-1$
private static final String TEST1_PROVBUNDLE_NAME = "test1";//$NON-NLS-1$
- private static final String TEST1_REQ_EE_FILTER = JAVA_EE_1_4_REQ;
+ private static final String TEST1_REQ_EE = JAVA_EE_1_4;
private static final String TEST2_REQ_A_NAME = "iua";//$NON-NLS-1$
private static final String TEST2_REQ_B_NAME = "iub";//$NON-NLS-1$
private static final String TEST2_REQ_C_NAME = "iuc";//$NON-NLS-1$
- private static final String TEST2_REQ_EE_FILTER = JAVA_EE_1_4_REQ;
+ private static final String TEST2_REQ_EE = JAVA_EE_1_4;
private static final String TEST2_PROV_Z_NAME = "iuz";//$NON-NLS-1$
private static final String TEST2_PROV_Y_NAME = "iuy";//$NON-NLS-1$
private static final String TEST2_PROV_X_NAME = "iux";//$NON-NLS-1$
@@ -99,9 +100,9 @@ public class BundlesActionTest extends ActionTest {
private static final String TEST4_REQ_PACKAGE_OPTGREEDY_NAME = "iuf";//$NON-NLS-1$
private static final String TEST4_REQ_BUNDLE_OPTIONAL_NAME = "iug";//$NON-NLS-1$
private static final String TEST4_REQ_BUNDLE_OPTGREEDY_NAME = "iuh";//$NON-NLS-1$
- private static final String TEST5_REQ_EE_FILTER = JAVA_EE_1_4_REQ;
+ private static final String TEST5_REQ_EE = JAVA_EE_1_4;
private static final String TEST5_PROV_BUNDLE_NAME = "test5";//$NON-NLS-1$
- private static final String TESTDYN_REQ_EE_FILTER = JAVA_EE_1_6_REQ;
+ private static final String TESTDYN_REQ_EE = JAVA_EE_1_6;
private static final File TEST_BASE = new File(TestActivator.getTestDataFolder(), "BundlesActionTest");//$NON-NLS-1$
private static final File TEST_FILE1 = new File(TEST_BASE, TEST1_PROVBUNDLE_NAME);
@@ -173,32 +174,32 @@ public class BundlesActionTest extends ActionTest {
bundlesAction.perform(info, results, new NullProgressMonitor());
Collection<IInstallableUnit> ius = results.getIUs(null, null);
- assertEquals("1.0", 1, ius.size());
+ assertEquals(1, ius.size());
info = new PublisherInfo();
results = new PublisherResult();
bundlesAction = new BundlesAction(new File[] {foo});
bundlesAction.perform(info, results, new NullProgressMonitor());
ius = results.getIUs(null, null);
- assertEquals("2.0", 1, ius.size());
+ assertEquals(1, ius.size());
QueryableArray queryableArray = new QueryableArray(ius.toArray(new IInstallableUnit[ius.size()]));
IQueryResult<IInstallableUnit> result = queryableArray.query(QueryUtil.createIUQuery("foo"), null);
- assertEquals("3.1", 1, queryResultSize(result));
+ assertEquals(1, queryResultSize(result));
IInstallableUnit iu = result.iterator().next();
TranslationSupport utils = new TranslationSupport();
utils.setTranslationSource(queryableArray);
- assertEquals("3.2", "English Foo", utils.getIUProperty(iu, IInstallableUnit.PROP_NAME));
+ assertEquals("English Foo", utils.getIUProperty(iu, IInstallableUnit.PROP_NAME));
bundlesAction = new BundlesAction(new File[] {foo_fragment});
bundlesAction.perform(info, results, new NullProgressMonitor());
ius = results.getIUs(null, null);
- assertEquals("2.0", 3, ius.size());
+ assertEquals(3, ius.size());
queryableArray = new QueryableArray(ius.toArray(new IInstallableUnit[ius.size()]));
result = queryableArray.query(QueryUtil.createIUQuery("foo"), null);
- assertEquals("2.1", 1, queryResultSize(result));
+ assertEquals(1, queryResultSize(result));
iu = result.iterator().next();
utils.setTranslationSource(queryableArray);
- assertEquals("2.2", "German Foo", utils.getIUProperty(iu, IInstallableUnit.PROP_NAME, Locale.GERMAN.toString()));
+ assertEquals("German Foo", utils.getIUProperty(iu, IInstallableUnit.PROP_NAME, Locale.GERMAN.toString()));
}
private void verifyBundlesAction() throws Exception {
@@ -217,7 +218,7 @@ public class BundlesActionTest extends ActionTest {
IArtifactDescriptor[] descriptors = artifactRepository.getArtifactDescriptors(key2);
// Should have one canonical and one packed
- assertTrue("1.0", descriptors.length == 2);
+ assertEquals(2, descriptors.length);
int packedIdx;
int canonicalIdx;
@@ -244,18 +245,18 @@ public class BundlesActionTest extends ActionTest {
}
private void verifyBundle1() {
- ArrayList<IInstallableUnit> ius = new ArrayList<>(publisherResult.getIUs(TEST1_PROVBUNDLE_NAME, IPublisherResult.ROOT));
- assertTrue(ius.size() == 1);
+ List<IInstallableUnit> ius = new ArrayList<>(publisherResult.getIUs(TEST1_PROVBUNDLE_NAME, IPublisherResult.ROOT));
+ assertEquals(1, ius.size());
IInstallableUnit bundle1IU = ius.get(0);
- assertNotNull("1.0", bundle1IU);
- assertEquals("1.1", bundle1IU.getVersion(), BUNDLE1_VERSION);
+ assertNotNull(bundle1IU);
+ assertEquals(bundle1IU.getVersion(), BUNDLE1_VERSION);
// check required capabilities
- Collection<IRequirement> requiredCapability = bundle1IU.getRequirements();
- verifyRequirement(requiredCapability, TEST1_IU_D_NAMESPACE, TEST1_IUD_NAME, TEST1_IU_D_VERSION_RANGE);
- verifyRequirement(requiredCapability, TEST1_REQ_EE_FILTER, 0, 1, true);
- assertEquals("2.0", 2, requiredCapability.size());
+ Collection<IRequirement> requirements = bundle1IU.getRequirements();
+ verifyRequirement(requirements, TEST1_IU_D_NAMESPACE, TEST1_IUD_NAME, TEST1_IU_D_VERSION_RANGE);
+ verifyRequirement(requirements, OSGI_EE, TEST1_REQ_EE, null, 1, 1, true);
+ assertEquals(2, requirements.size());
// check provided capabilities
Collection<IProvidedCapability> providedCapabilities = bundle1IU.getProvidedCapabilities();
@@ -264,7 +265,7 @@ public class BundlesActionTest extends ActionTest {
verifyProvidedCapability(providedCapabilities, OSGI, TEST1_PROVBUNDLE_NAME, BUNDLE1_VERSION);
verifyProvidedCapability(providedCapabilities, TEST1_PROV_Z_NAMESPACE, TEST1_PROVZ_NAME, TEST2_PROVZ_VERSION);
verifyProvidedCapability(providedCapabilities, PublisherHelper.NAMESPACE_ECLIPSE_TYPE, "source", Version.create("1.0.0"));//$NON-NLS-1$//$NON-NLS-2$
- assertEquals("2.1", 5, providedCapabilities.size());
+ assertEquals(5, providedCapabilities.size());
Collection<ITouchpointData> data = bundle1IU.getTouchpointData();
boolean found = false;
@@ -277,27 +278,27 @@ public class BundlesActionTest extends ActionTest {
found = true;
}
}
- assertTrue("3.0", found);
+ assertTrue(found);
}
private void verifyBundle2() {
- ArrayList<IInstallableUnit> ius = new ArrayList<>(publisherResult.getIUs(TEST2_PROV_BUNDLE_NAME, IPublisherResult.ROOT));
- assertTrue(ius.size() == 1);
- IInstallableUnit bundle2IU = ius.get(0);
+ List<IInstallableUnit> ius = new ArrayList<>(publisherResult.getIUs(TEST2_PROV_BUNDLE_NAME, IPublisherResult.ROOT));
+ assertEquals(1, ius.size());
- assertNotNull(bundle2IU);
- assertEquals(bundle2IU.getVersion(), BUNDLE2_VERSION);
+ IInstallableUnit bundleIu = ius.get(0);
+ assertNotNull(bundleIu);
+ assertEquals(bundleIu.getVersion(), BUNDLE2_VERSION);
// check required capabilities
- Collection<IRequirement> requirements = bundle2IU.getRequirements();
+ Collection<IRequirement> requirements = bundleIu.getRequirements();
verifyRequirement(requirements, TEST2_IU_A_NAMESPACE, TEST2_REQ_A_NAME, TEST2_IU_A_VERSION_RANGE);
verifyRequirement(requirements, TEST2_IU_B_NAMESPACE, TEST2_REQ_B_NAME, TEST2_IU_B_VERSION_RANGE);
verifyRequirement(requirements, TEST2_IU_C_NAMESPACE, TEST2_REQ_C_NAME, TEST2_IU_C_VERSION_RANGE);
- verifyRequirement(requirements, TEST2_REQ_EE_FILTER, 0, 1, true);
- assertTrue(requirements.size() == 4 /*number of tested elements*/);
+ verifyRequirement(requirements, OSGI_EE, TEST2_REQ_EE, null, 1, 1, true);
+ assertEquals(4, requirements.size());
// check provided capabilities
- Collection<IProvidedCapability> providedCapabilities = bundle2IU.getProvidedCapabilities();
+ Collection<IProvidedCapability> providedCapabilities = bundleIu.getProvidedCapabilities();
verifyProvidedCapability(providedCapabilities, PROVBUNDLE_NAMESPACE, TEST2_PROV_BUNDLE_NAME, PROVBUNDLE2_VERSION);
verifyProvidedCapability(providedCapabilities, OSGI, TEST2_PROV_BUNDLE_NAME, BUNDLE2_VERSION);
verifyProvidedCapability(providedCapabilities, OSGI_IDENTITY, TEST2_PROV_BUNDLE_NAME, BUNDLE2_VERSION);
@@ -308,11 +309,11 @@ public class BundlesActionTest extends ActionTest {
assertEquals(7, providedCapabilities.size()); /*number of tested elements*/
// check %bundle name is correct
- Map<String, String> prop = bundle2IU.getProperties();
+ Map<String, String> prop = bundleIu.getProperties();
assertTrue(prop.get("org.eclipse.equinox.p2.name").toString().equalsIgnoreCase("%bundleName"));//$NON-NLS-1$//$NON-NLS-2$
assertTrue(prop.get("org.eclipse.equinox.p2.provider").toString().equalsIgnoreCase("%providerName"));//$NON-NLS-1$//$NON-NLS-2$
- Collection<ITouchpointData> data = bundle2IU.getTouchpointData();
+ Collection<ITouchpointData> data = bundleIu.getTouchpointData();
boolean found = false;
for (ITouchpointData td : data) {
ITouchpointInstruction configure = td.getInstruction("configure");
@@ -323,18 +324,17 @@ public class BundlesActionTest extends ActionTest {
found = true;
}
}
- assertFalse("3.0", found);
-
+ assertFalse(found);
}
private void verifyBundle3() {
// also a regression test for bug 393051: manifest headers use uncommon (but valid) capitalization
ArrayList<IInstallableUnit> ius = new ArrayList<>(publisherResult.getIUs(TEST3_PROV_BUNDLE_NAME, IPublisherResult.ROOT));
+ assertEquals(1, ius.size());
- assertTrue(ius.size() == 1);
- IInstallableUnit bundle3IU = ius.get(0);
+ IInstallableUnit bundleIu = ius.get(0);
- IUpdateDescriptor updateDescriptor = bundle3IU.getUpdateDescriptor();
+ IUpdateDescriptor updateDescriptor = bundleIu.getUpdateDescriptor();
String name = RequiredCapability.extractName(updateDescriptor.getIUsBeingUpdated().iterator().next());
VersionRange range = RequiredCapability.extractRange(updateDescriptor.getIUsBeingUpdated().iterator().next());
String description = updateDescriptor.getDescription();
@@ -349,36 +349,31 @@ public class BundlesActionTest extends ActionTest {
private void verifyBundle4() {
ArrayList<IInstallableUnit> ius = new ArrayList<>(publisherResult.getIUs(TEST4_PROV_BUNDLE_NAME, IPublisherResult.ROOT));
- assertTrue(ius.size() == 1);
- IInstallableUnit bundle4IU = ius.get(0);
+ assertEquals(1, ius.size());
- assertNotNull("1.0", bundle4IU);
- assertEquals("1.1", bundle4IU.getVersion(), BUNDLE4_VERSION);
+ IInstallableUnit bundleIu = ius.get(0);
+ assertNotNull(bundleIu);
+ assertEquals(bundleIu.getVersion(), BUNDLE4_VERSION);
// check required capabilities
- Collection<IRequirement> requirements = bundle4IU.getRequirements();
+ Collection<IRequirement> requirements = bundleIu.getRequirements();
verifyRequirement(requirements, JAVA_PACKAGE, TEST4_REQ_PACKAGE_OPTIONAL_NAME, DEFAULT_VERSION_RANGE, null, 0, 1, false);
verifyRequirement(requirements, JAVA_PACKAGE, TEST4_REQ_PACKAGE_OPTGREEDY_NAME, DEFAULT_VERSION_RANGE, null, 0, 1, true);
verifyRequirement(requirements, OSGI, TEST4_REQ_BUNDLE_OPTIONAL_NAME, DEFAULT_VERSION_RANGE, null, 0, 1, false);
verifyRequirement(requirements, OSGI, TEST4_REQ_BUNDLE_OPTGREEDY_NAME, DEFAULT_VERSION_RANGE, null, 0, 1, true);
- assertEquals("2.0", 4, requirements.size());
+ assertEquals(4, requirements.size());
}
private void verifyBundle5() {
ArrayList<IInstallableUnit> ius = new ArrayList<>(publisherResult.getIUs(TEST5_PROV_BUNDLE_NAME, IPublisherResult.ROOT));
- assertTrue(ius.size() == 1);
+ assertEquals(1, ius.size());
+
IInstallableUnit bundle5IU = ius.get(0);
Collection<IRequirement> requirements = bundle5IU.getRequirements();
- verifyRequirement(requirements, TEST5_REQ_EE_FILTER, 0, 1, true);
- assertTrue(requirements.size() == 2);
- IRequirement requirement = requirements.iterator().next();
-
- int min = requirement.getMin();
- int max = requirement.getMax();
-
- assertTrue(min == 6);
- assertTrue(max == 7);
+ verifyRequirement(requirements, OSGI_EE, TEST5_REQ_EE, null, 1, 1, true);
+ verifyRequirement(requirements, "bar", "foo", VersionRange.emptyRange, null, 6, 7, true);
+ assertEquals(2, requirements.size());
}
@Override
@@ -491,7 +486,7 @@ public class BundlesActionTest extends ActionTest {
IInstallableUnit iu = BundlesAction.createBundleIU(BundlesAction.createBundleDescription(testData), null, new PublisherInfo());
Collection<IRequirement> requirements = iu.getRequirements();
- verifyRequirement(requirements, TESTDYN_REQ_EE_FILTER, 0, 1, true);
+ verifyRequirement(requirements, OSGI_EE, TESTDYN_REQ_EE, null, 1, 1, true);
assertEquals(1, requirements.size());
}

Back to the top