diff options
author | Thomas Watson | 2018-01-22 17:45:31 +0000 |
---|---|---|
committer | Thomas Watson | 2018-01-22 17:45:31 +0000 |
commit | 0e3caa9359428dcb20c1dc3a2c580fff64777d3d (patch) | |
tree | 491a0aa61382ad685c708f7c5c3943af043f5738 /bundles | |
parent | 81563662fc363e85f9311289f2e9026ecfacd390 (diff) | |
download | rt.equinox.p2-0e3caa9359428dcb20c1dc3a2c580fff64777d3d.tar.gz rt.equinox.p2-0e3caa9359428dcb20c1dc3a2c580fff64777d3d.tar.xz rt.equinox.p2-0e3caa9359428dcb20c1dc3a2c580fff64777d3d.zip |
Revert "Bug 528387 - Dedicated xml elements for generic requirements"
This reverts commit a7a99e1fa49938a8f62d44d5c443d38981afeace.
Diffstat (limited to 'bundles')
27 files changed, 755 insertions, 1315 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 4243ad59d..ed67c081a 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, 2, 0); + public static final Version CURRENT_VERSION = Version.createOSGi(1, 1, 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 024631745..20fc56a8d 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,14 +12,11 @@ *******************************************************************************/ 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.ArtifactKey; -import org.eclipse.equinox.internal.p2.metadata.InstallableUnit; +import org.eclipse.equinox.internal.p2.metadata.*; import org.eclipse.equinox.internal.p2.persistence.XMLParser; import org.eclipse.equinox.p2.metadata.*; import org.eclipse.equinox.p2.metadata.MetadataFactory.*; @@ -33,6 +30,18 @@ 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); } @@ -313,7 +322,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.getRequirements()); + IRequirement[] requiredCapabilities = (requiredCapabilitiesHandler == null ? new IRequirement[0] : requiredCapabilitiesHandler.getRequiredCapabilities()); currentUnit.setRequirements(requiredCapabilities); IRequirement[] metaRequiredCapabilities = (metaRequiredCapabilitiesHandler == null ? new IRequirement[0] : metaRequiredCapabilitiesHandler.getMetaRequiredCapabilities()); currentUnit.setMetaRequirements(metaRequiredCapabilities); @@ -380,7 +389,7 @@ public abstract class MetadataParser extends XMLParser implements XMLConstants { @Override protected void finished() { if (children != null) { - scopes.add(children.getRequirements()); + scopes.add(children.getRequiredCapabilities()); } } } @@ -508,7 +517,7 @@ public abstract class MetadataParser extends XMLParser implements XMLConstants { private String namespace; private String name; private Version version; - private ProvidedCapabilityPropertiesHandler propertiesHandler; + private ProvidedCapabilityAttributesHandler attributesHandler; private List<IProvidedCapability> capabilities; @@ -525,68 +534,63 @@ public abstract class MetadataParser extends XMLParser implements XMLConstants { @Override public void startElement(String elem, Attributes attributes) { - switch (elem) { - case PROPERTIES_ELEMENT : - this.propertiesHandler = new ProvidedCapabilityPropertiesHandler(this, attributes); - break; - default : - invalidElement(elem, attributes); - break; + if (elem.equals(CAPABILITY_ATTRIBUTES_ELEMENT)) { + this.attributesHandler = new ProvidedCapabilityAttributesHandler(this, attributes); + } else { + invalidElement(elem, attributes); } } @Override protected void finished() { - Map<String, Object> properties = (propertiesHandler != null) - ? propertiesHandler.getProperties() + Map<String, Object> capAttrs = (attributesHandler != null) + ? attributesHandler.getAttributes() : new HashMap<>(); - properties.put(namespace, name); - properties.put(IProvidedCapability.PROPERTY_VERSION, version); - IProvidedCapability cap = MetadataFactory.createProvidedCapability(namespace, properties); + capAttrs.put(namespace, name); + capAttrs.put(ProvidedCapability.ATTRIBUTE_VERSION, version); + IProvidedCapability cap = MetadataFactory.createProvidedCapability(namespace, capAttrs); capabilities.add(cap); } } - protected class ProvidedCapabilityPropertiesHandler extends AbstractMetadataHandler { - private Map<String, Object> properties; + protected class ProvidedCapabilityAttributesHandler extends AbstractMetadataHandler { + private Map<String, Object> capAttributes; - public ProvidedCapabilityPropertiesHandler(AbstractHandler parentHandler, Attributes attributes) { - super(parentHandler, PROPERTIES_ELEMENT); - this.properties = new HashMap<>(getOptionalSize(attributes, 2)); + public ProvidedCapabilityAttributesHandler(AbstractHandler parentHandler, Attributes attributes) { + super(parentHandler, CAPABILITY_ATTRIBUTES_ELEMENT); + // TODO add getOptionalSize(attributes, 4) + this.capAttributes = new HashMap<>(); } - public Map<String, Object> getProperties() { - return properties; + public Map<String, Object> getAttributes() { + return capAttributes; } @Override - public void startElement(String elem, Attributes attributes) { - switch (elem) { - case PROPERTY_ELEMENT : - new ProvidedCapabilityPropertyHandler(this, attributes, properties); - break; - default : - invalidElement(elem, attributes); - break; + public void startElement(String name, Attributes attributes) { + if (name.equals(CAPABILITY_ATTRIBUTE_ELEMENT)) { + new ProvidedCapabilityAttributeHandler(this, attributes, capAttributes); + } else { + invalidElement(name, attributes); } } } - protected class ProvidedCapabilityPropertyHandler extends AbstractMetadataHandler { - public ProvidedCapabilityPropertyHandler(AbstractHandler parentHandler, Attributes attributes, Map<String, Object> properties) { - super(parentHandler, PROPERTY_ELEMENT); + protected class ProvidedCapabilityAttributeHandler extends AbstractMetadataHandler { + public ProvidedCapabilityAttributeHandler(AbstractHandler parentHandler, Attributes attributes, Map<String, Object> capAttributes) { + super(parentHandler, CAPABILITY_ATTRIBUTE_ELEMENT); - String[] values = parseAttributes(attributes, PROPERTY_ATTRIBUTES, PROPERTY_OPTIONAL_ATTRIBUTES); + String[] values = parseRequiredAttributes(attributes, CAPABILITY_ATTRIBUTE_REQUIRED_ATTRIBUTES); String name = values[0]; String value = values[1]; - String type = values[2] == null ? PROPERTY_TYPE_STRING : values[2]; + String type = values[2]; - if (type.startsWith(PROPERTY_TYPE_LIST)) { - properties.put(name, parseList(type, value)); + if (type.startsWith(ATTR_TYPE_LIST_HEAD)) { + capAttributes.put(name, parseList(type, value)); } else { - properties.put(name, parseScalar(type, value)); + capAttributes.put(name, parseScalar(type, value)); } } @@ -596,53 +600,49 @@ public abstract class MetadataParser extends XMLParser implements XMLConstants { } private List<Object> parseList(String type, String value) { - 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; + 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)); } - return Arrays.stream(value.split("\\s*,\\s*")) //$NON-NLS-1$ - .map(val -> parseScalar(elType, val)) - .collect(toList()); + return res; } private Object parseScalar(String type, String value) { - if (PROPERTY_TYPE_STRING.equals(type)) { + if (ATTR_TYPE_STRING.equals(type)) { return value; } - if (PROPERTY_TYPE_INTEGER.equals(type)) { + if (ATTR_TYPE_INTEGER.equals(type)) { return Integer.parseInt(value); } - if (PROPERTY_TYPE_LONG.equals(type)) { + if (ATTR_TYPE_LONG.equals(type)) { return Long.parseLong(value); } - if (PROPERTY_TYPE_FLOAT.equals(type)) { + if (ATTR_TYPE_FLOAT.equals(type)) { return Float.parseFloat(value); } - if (PROPERTY_TYPE_DOUBLE.equals(type)) { + if (ATTR_TYPE_DOUBLE.equals(type)) { return Double.parseDouble(value); } - if (PROPERTY_TYPE_BYTE.equals(type)) { + if (ATTR_TYPE_BYTE.equals(type)) { return Byte.parseByte(value); } - if (PROPERTY_TYPE_SHORT.equals(type)) { + if (ATTR_TYPE_SHORT.equals(type)) { return Short.parseShort(value); } - if (PROPERTY_TYPE_CHARACTER.equals(type)) { + if (ATTR_TYPE_CHARACTER.equals(type)) { return value.charAt(0); } - if (PROPERTY_TYPE_BOOLEAN.equals(type)) { + if (ATTR_TYPE_BOOLEAN.equals(type)) { return Boolean.parseBoolean(value); } - if (PROPERTY_TYPE_VERSION.equals(type)) { + if (ATTR_TYPE_VERSION.equals(type)) { return Version.create(value); } - - // String is the default - return value; + // TODO Throw what? + return value.toString(); } } @@ -691,29 +691,23 @@ public abstract class MetadataParser extends XMLParser implements XMLConstants { } protected class RequirementsHandler extends AbstractMetadataHandler { - private List<IRequirement> requirements; + private List<IRequirement> requiredCapabilities; public RequirementsHandler(AbstractHandler parentHandler, Attributes attributes) { super(parentHandler, REQUIREMENTS_ELEMENT); - requirements = new ArrayList<>(getOptionalSize(attributes, 4)); + requiredCapabilities = new ArrayList<>(getOptionalSize(attributes, 4)); } - public IRequirement[] getRequirements() { - return requirements.toArray(new IRequirement[requirements.size()]); + public IRequirement[] getRequiredCapabilities() { + return requiredCapabilities.toArray(new IRequirement[requiredCapabilities.size()]); } @Override public void startElement(String name, Attributes 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; + if (name.equals(REQUIREMENT_ELEMENT)) { + new RequirementHandler(this, attributes, requiredCapabilities); + } else { + invalidElement(name, attributes); } } } @@ -740,34 +734,31 @@ 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, REQUIRED_CAPABILITY_OPTIONAL_ATTRIBUTES); + String[] values = parseAttributes(attributes, REQIURED_CAPABILITY_ATTRIBUTES, OPTIONAL_CAPABILITY_ATTRIBUTES); namespace = values[0]; name = values[1]; range = checkVersionRange(REQUIREMENT_ELEMENT, VERSION_RANGE_ATTRIBUTE, values[2]); - boolean isOptional = checkBoolean(REQUIREMENT_ELEMENT, REQUIRED_CAPABILITY_OPTIONAL_ATTRIBUTE, values[3], false).booleanValue(); + boolean isOptional = checkBoolean(REQUIREMENT_ELEMENT, CAPABILITY_OPTIONAL_ATTRIBUTE, values[3], false).booleanValue(); min = isOptional ? 0 : 1; - boolean isMultiple = checkBoolean(REQUIREMENT_ELEMENT, REQUIRED_CAPABILITY_MULTIPLE_ATTRIBUTE, values[4], false).booleanValue(); + boolean isMultiple = checkBoolean(REQUIREMENT_ELEMENT, CAPABILITY_MULTIPLE_ATTRIBUTE, values[4], false).booleanValue(); max = isMultiple ? Integer.MAX_VALUE : 1; - 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); + greedy = checkBoolean(REQUIREMENT_ELEMENT, CAPABILITY_GREED_ATTRIBUTE, values[5], true).booleanValue(); + } else { + // Expression based requirement + String[] values = parseAttributes(attributes, REQIUREMENT_ATTRIBUTES, OPTIONAL_REQUIREMENT_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, REQUIREMENT_GREED_ATTRIBUTE, values[4], true).booleanValue(); + greedy = checkBoolean(REQUIREMENT_ELEMENT, CAPABILITY_GREED_ATTRIBUTE, values[4], true).booleanValue(); } } @Override public void startElement(String elem, Attributes attributes) { - if (elem.equals(REQUIREMENT_FILTER_ELEMENT)) { - filterHandler = new TextHandler(this, REQUIREMENT_FILTER_ELEMENT, attributes); + if (elem.equals(CAPABILITY_FILTER_ELEMENT)) { + filterHandler = new TextHandler(this, CAPABILITY_FILTER_ELEMENT, attributes); } else if (elem.equals(REQUIREMENT_DESCRIPTION_ELEMENT)) { descriptionHandler = new TextHandler(this, REQUIREMENT_DESCRIPTION_ELEMENT, attributes); } else { @@ -814,83 +805,6 @@ 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 f88d52bdd..2b7686e35 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,10 +14,11 @@ 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.*; @@ -95,23 +96,23 @@ public class MetadataWriter extends XMLWriter implements XMLConstants { private boolean hasOnlySimpleRequirements(IInstallableUnit iu) { for (IRequirement r : iu.getRequirements()) - if (r.getMax() == 0 || !RequiredCapability.isVersionRangeRequirement(r.getMatches())) + if (r.getMax() == 0 || !RequiredCapability.isSimpleRequirement(r.getMatches())) return false; if (iu.getUpdateDescriptor() != null) { for (IMatchExpression<IInstallableUnit> m : iu.getUpdateDescriptor().getIUsBeingUpdated()) { - if (!RequiredCapability.isVersionRangeRequirement(m)) + if (!RequiredCapability.isSimpleRequirement(m)) return false; } } for (IRequirement r : iu.getMetaRequirements()) - if (r.getMax() == 0 || !RequiredCapability.isVersionRangeRequirement(r.getMatches())) + if (r.getMax() == 0 || !RequiredCapability.isSimpleRequirement(r.getMatches())) return false; if (iu instanceof IInstallableUnitFragment) { for (IRequirement r : ((IInstallableUnitFragment) iu).getHost()) - if (!RequiredCapability.isVersionRangeRequirement(r.getMatches())) + if (!RequiredCapability.isSimpleRequirement(r.getMatches())) return false; } @@ -119,11 +120,11 @@ public class MetadataWriter extends XMLWriter implements XMLConstants { IInstallableUnitPatch iuPatch = (IInstallableUnitPatch) iu; for (IRequirement[] rArr : iuPatch.getApplicabilityScope()) for (IRequirement r : rArr) - if (!RequiredCapability.isVersionRangeRequirement(r.getMatches())) + if (!RequiredCapability.isSimpleRequirement(r.getMatches())) return false; IRequirement lifeCycle = iuPatch.getLifeCycle(); - if (lifeCycle != null && !RequiredCapability.isVersionRangeRequirement(lifeCycle.getMatches())) + if (lifeCycle != null && !RequiredCapability.isSimpleRequirement(lifeCycle.getMatches())) return false; } return true; @@ -166,12 +167,50 @@ public class MetadataWriter extends XMLWriter implements XMLConstants { attribute(NAME_ATTRIBUTE, capability.getName()); attribute(VERSION_ATTRIBUTE, capability.getVersion()); - Map<String, Object> props = new HashMap<>(capability.getProperties()); - props.remove(capability.getNamespace()); - props.remove(IProvidedCapability.PROPERTY_VERSION); + Map<String, Object> attrs = new HashMap<>(capability.getAttributes()); + attrs.remove(capability.getNamespace()); + attrs.remove(ProvidedCapability.ATTRIBUTE_VERSION); - if (!props.isEmpty()) { - writeProperties(props); + 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); } end(PROVIDED_CAPABILITY_ELEMENT); @@ -207,7 +246,7 @@ public class MetadataWriter extends XMLWriter implements XMLConstants { throw new IllegalStateException(); IMatchExpression<IInstallableUnit> singleUD = descriptor.getIUsBeingUpdated().iterator().next(); start(UPDATE_DESCRIPTOR_ELEMENT); - if (RequiredCapability.isVersionRangeRequirement(singleUD)) { + if (RequiredCapability.isSimpleRequirement(singleUD)) { attribute(ID_ATTRIBUTE, RequiredCapability.extractName(singleUD)); attribute(VERSION_RANGE_ATTRIBUTE, RequiredCapability.extractRange(singleUD)); } else { @@ -252,59 +291,27 @@ public class MetadataWriter extends XMLWriter implements XMLConstants { } protected void writeRequirement(IRequirement requirement) { + start(REQUIREMENT_ELEMENT); IMatchExpression<IInstallableUnit> match = requirement.getMatches(); - - // A (namespace, name, version-range) type of requirement - if (requirement.getMax() > 0 && RequiredCapability.isVersionRangeRequirement(match)) { - start(REQUIREMENT_ELEMENT); - + if (requirement.getMax() > 0 && RequiredCapability.isSimpleRequirement(match)) { attribute(NAMESPACE_ATTRIBUTE, RequiredCapability.extractNamespace(match)); attribute(NAME_ATTRIBUTE, RequiredCapability.extractName(match)); attribute(VERSION_RANGE_ATTRIBUTE, RequiredCapability.extractRange(match)); - 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); - + attribute(CAPABILITY_OPTIONAL_ATTRIBUTE, requirement.getMin() == 0, false); + attribute(CAPABILITY_MULTIPLE_ATTRIBUTE, requirement.getMax() > 1, false); + } else { 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()); } - - if (requirement.getDescription() != null) { + attribute(CAPABILITY_GREED_ATTRIBUTE, requirement.isGreedy(), true); + if (requirement.getFilter() != null) + writeTrimmedCdata(CAPABILITY_FILTER_ELEMENT, requirement.getFilter().getParameters()[0].toString()); + if (requirement.getDescription() != null) writeTrimmedCdata(REQUIREMENT_DESCRIPTION_ELEMENT, requirement.getDescription()); - } - - end(); + end(REQUIREMENT_ELEMENT); } 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 621356e4a..44db99925 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,7 +39,9 @@ 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$ @@ -61,26 +63,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 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 CAPABILITY_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$ - 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}; + // 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[] 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 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[] 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}; + 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}; // 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 31297abf8..13eb67642 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,14 +9,10 @@ * 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; @@ -35,65 +31,44 @@ 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 #getProperties} method */ - public static final String MEMBER_PROPERTIES = "properties"; //$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$ private final String namespace; - private final Map<String, Object> properties; + private final Map<String, Object> attributes; - public ProvidedCapability(String namespace, Map<String, Object> props) { + public ProvidedCapability(String namespace, Map<String, Object> attrs) { Assert.isNotNull(namespace, NLS.bind(Messages.provided_capability_namespace_not_defined, null)); this.namespace = namespace; - Assert.isNotNull(props); - Assert.isTrue(!props.isEmpty()); - - assertValidPropertyTypes(props); + Assert.isNotNull(attrs); + Assert.isTrue(!attrs.isEmpty()); - Map<String, Object> resolvedProps = new HashMap<>(props); + this.attributes = new HashMap<>(attrs); // Verify the name - Assert.isTrue(resolvedProps.containsKey(namespace) && (resolvedProps.get(namespace) instanceof String), NLS.bind(Messages.provided_capability_name_not_defined, namespace)); + Assert.isTrue(attributes.containsKey(namespace) && (attributes.get(namespace) instanceof String), NLS.bind(Messages.provided_capability_name_not_defined, namespace)); // Verify the version - Object version = resolvedProps.get(PROPERTY_VERSION); + Object version = attributes.get(ATTRIBUTE_VERSION); if (version != null) { - Assert.isTrue(props.get(PROPERTY_VERSION) instanceof Version); + Assert.isTrue(attributes.get(ATTRIBUTE_VERSION) instanceof Version); } else { - resolvedProps.put(PROPERTY_VERSION, Version.emptyVersion); + attributes.put(ATTRIBUTE_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.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(); + this.attributes = new HashMap<>(); + attributes.put(namespace, name); + attributes.put(ATTRIBUTE_VERSION, version == null ? Version.emptyVersion : version); } @Override @@ -112,7 +87,7 @@ public class ProvidedCapability implements IProvidedCapability, IMemberProvider return false; } - if (!(properties.equals(otherCapability.getProperties()))) { + if (!(attributes.equals(otherCapability.getAttributes()))) { return false; } @@ -126,17 +101,38 @@ public class ProvidedCapability implements IProvidedCapability, IMemberProvider @Override public String getName() { - return (String) properties.get(namespace); + return (String) attributes.get(namespace); } @Override public Version getVersion() { - return (Version) properties.get(PROPERTY_VERSION); + return (Version) attributes.get(ATTRIBUTE_VERSION); } @Override - public Map<String, Object> getProperties() { - return properties; + 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(); } @Override @@ -145,36 +141,13 @@ public class ProvidedCapability implements IProvidedCapability, IMemberProvider case MEMBER_NAMESPACE : return namespace; case MEMBER_NAME : - return properties.get(namespace); + return attributes.get(namespace); case MEMBER_VERSION : - return properties.get(PROPERTY_VERSION); - case MEMBER_PROPERTIES : - return properties; + return attributes.get(ATTRIBUTE_VERSION); + case MEMBER_ATTRIBUTES : + return attributes; default : - 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); + throw new IllegalArgumentException("No such member: " + memberName); //$NON-NLS-1$ } } - - 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 c08af575d..cd8f8dac8 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,14 +39,27 @@ import org.eclipse.equinox.p2.metadata.expression.IMatchExpression; * @see IInstallableUnit#NAMESPACE_IU_ID */ public class RequiredCapability extends Requirement implements IRequiredCapability { - /** - * 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)); + 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))); + } /** * TODO Remove. This is a private impl class. Users must call the analogous MetadataFactory.createRequirement() @@ -91,11 +104,17 @@ public class RequiredCapability extends Requirement implements IRequiredCapabili public String toString() { StringBuilder result = new StringBuilder(); + // Namespace result.append(getNamespace()); - result.append("; "); //$NON-NLS-1$ + result.append(' '); + + // Name result.append(getName()); - result.append(" "); //$NON-NLS-1$ - result.append(getRange()); + result.append(' '); + + // Version range + VersionRange range = getRange(); + result.append(range); return result.toString(); } @@ -105,7 +124,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(VERSION_RANGE_MATCH, name, namespace, resolvedRange); + return factory.matchExpression(simpleMatchExpression, name, namespace, resolvedRange); } public static String extractNamespace(IMatchExpression<IInstallableUnit> matchExpression) { @@ -125,7 +144,7 @@ public class RequiredCapability extends Requirement implements IRequiredCapabili } public static boolean isVersionStrict(IMatchExpression<IInstallableUnit> matchExpression) { - if (!isVersionRangeRequirement(matchExpression)) { + if (!isSimpleRequirement(matchExpression)) { return false; } @@ -134,12 +153,12 @@ public class RequiredCapability extends Requirement implements IRequiredCapabili return range.getMinimum().equals(range.getMaximum()); } - public static boolean isVersionRangeRequirement(IMatchExpression<IInstallableUnit> matchExpression) { - return VERSION_RANGE_MATCH.equals(ExpressionUtil.getOperand(matchExpression)); + public static boolean isSimpleRequirement(IMatchExpression<IInstallableUnit> matchExpression) { + return simpleMatchExpression.equals(ExpressionUtil.getOperand(matchExpression)); } private static void assertValid(IMatchExpression<IInstallableUnit> matchExpression) { - if (!isVersionRangeRequirement(matchExpression)) { + if (!isSimpleRequirement(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 deleted file mode 100644 index a108fadc0..000000000 --- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/RequiredPropertiesMatch.java +++ /dev/null @@ -1,84 +0,0 @@ -/******************************************************************************* - * 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 5fe660e82..036721c5f 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,11 +11,7 @@ *******************************************************************************/ package org.eclipse.equinox.internal.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.*; import org.eclipse.equinox.p2.metadata.expression.IMatchExpression; import org.eclipse.equinox.p2.metadata.expression.IMemberProvider; @@ -70,14 +66,10 @@ public class Requirement implements IRequirement, IMemberProvider { // Parameters Object[] params = matchExpression.getParameters(); if (params.length > 0) { - result.append(" ("); //$NON-NLS-1$ + result.append(' '); for (int i = 0; i < params.length; i++) { - if (i > 0) { - result.append(", "); //$NON-NLS-1$ - } - result.append(params[i]); + result.append(params[i]).append(' '); } - 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 c6d31687d..6cb8008f7 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,6 +229,8 @@ 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); @@ -331,7 +333,7 @@ public abstract class CoercingComparator<T> { * @return The coercing comparator */ @SuppressWarnings("unchecked") - public static <V> CoercingComparator<V> getComparator(V value, Object v2) { + public static <V extends Object> 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 8d89b2d13..d7b2b3cac 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.isVersionRangeRequirement(rm) ? concatenateUnique(queriedKeys, rm.getParameters()[0]) : getRequirementIDs(rm.createContext(), ((Unary) rm).operand, queriedKeys); + return RequiredCapability.isSimpleRequirement(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.isVersionRangeRequirement(rm) ? concatenateUnique(queriedKeys, rm.getParameters()[0]) : getRequirementIDs(rm.createContext(), ((Unary) rm).operand, queriedKeys); + queriedKeys = RequiredCapability.isSimpleRequirement(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 ac979c288..aa3b72b2e 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 capability is not defined +provided_capability_namespace_not_defined=the namespace of the provided capabilty 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 7cf08a170..de61165eb 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,13 +6,11 @@ * * Contributors: * EclipseSource - initial API and implementation -* IBM - ongoing development -* Todor Boev + * IBM - ongoing development ******************************************************************************/ 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 @@ -31,56 +29,45 @@ import org.eclipse.equinox.p2.metadata.expression.IFilterExpression; */ 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. */ - String getNamespace(); + public String getNamespace(); /** * - * @return String the attribute stored under a key equal to the {@link #getNamespace()} attribute of this capability. + * @return String the attribute stored under a key equal to {@link #getNamespace()} attribute of this capability. * @noreference This method is not intended to be referenced by clients. */ - String getName(); + public String getName(); /** * - * @return String the special {@link #PROPERTY_VERSION} attribute of this capability. + * @return String the special <code>version</code> attribute of this capability. * @noreference This method is not intended to be referenced by clients. */ - Version getVersion(); + public 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 An unmodifiable map + * @return A full description of this capability * @noreference This method is not intended to be referenced by clients. * @since 2.4 */ - Map<String, Object> getProperties(); + public Map<String, Object> getAttributes(); /** * 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> - * <li>The result of {@link #getNamespace()} on both objects are equal</li> - * <li>The result of {@link #getProperties()} on both objects are equal</li> + * <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 * </ul> */ @Override - boolean equals(Object other); + public 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 6c9d91a77..e3f89b18d 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,7 +30,6 @@ 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; @@ -38,8 +37,6 @@ 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; /** @@ -464,29 +461,11 @@ public final class MetadataFactory { * Returns a {@link IProvidedCapability} with the given values. * * @param namespace The capability namespace - * @param properties The description of the capability + * @param attributes The description of the capability * @since 2.4 */ - 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); + public static IProvidedCapability createProvidedCapability(String namespace, Map<String, Object> attributes) { + return new ProvidedCapability(namespace, attributes); } /** @@ -528,81 +507,87 @@ public final class MetadataFactory { /** * 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 requirement the match expression * @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(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> 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); + } - /** - * - * @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); + return new Requirement(requirement, filter, minCard, maxCard, greedy, null); } /** + * Create and return a new requirement ({@link IRequirement}) with the specified values. * - * @param namespace - * @param propsFilter - * @param envFilter - * @param minCard - * @param maxCard - * @param greedy - * @param description + * @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 - * @since 2.4 */ - 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); + 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); } /** * Create and return a new requirement ({@link IRequirement}) with the specified values. * - * @param requirement the match expression - * @param envFilter The filter used to evaluate whether this capability is applicable in the + * @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> envFilter, int minCard, int maxCard, boolean greedy) { - return createRequirementInternal(requirement, envFilter, 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); } /** * Create and return a new requirement ({@link IRequirement}) with the specified values. * * @param requirement the match expression - * @param envFilter the filter, or <code>null</code> + * @param filter 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> envFilter, int minCard, int maxCard, boolean greedy, String description) { - return createRequirementInternal(requirement, envFilter, minCard, maxCard, greedy, description); + 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); } /** @@ -752,14 +737,6 @@ 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); } @@ -793,26 +770,6 @@ 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 36dbe0f51..5ff218a9e 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,8 +39,6 @@ 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 c2ec094be..b3411b045 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,9 +12,6 @@ ******************************************************************************/ 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; @@ -31,7 +28,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.IMatchExpression; +import org.eclipse.equinox.p2.metadata.expression.*; import org.eclipse.equinox.p2.publisher.*; import org.eclipse.equinox.p2.publisher.actions.*; import org.eclipse.equinox.p2.query.IQueryResult; @@ -46,8 +43,6 @@ 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 @@ -83,6 +78,7 @@ 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)); @@ -198,7 +194,7 @@ public class BundlesAction extends AbstractPublisherAction { // Process generic requirements ManifestElement[] rawRequireCapHeader = parseManifestHeader(Constants.REQUIRE_CAPABILITY, manifest, bd.getLocation()); for (GenericSpecification requiredCap : bd.getGenericRequires()) { - addRequirement(requirements, requiredCap, rawRequireCapHeader); + addGenericRequirement(requirements, requiredCap, rawRequireCapHeader); } iu.setRequirements(requirements.toArray(new IRequirement[requirements.size()])); @@ -227,7 +223,7 @@ public class BundlesAction extends AbstractPublisherAction { int capNo = 0; for (GenericDescription genericCap : bd.getGenericCapabilities()) { - addCapability(providedCapabilities, genericCap, iu, capNo); + addGenericCapability(providedCapabilities, genericCap, iu, capNo); capNo++; } @@ -305,45 +301,36 @@ 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)); } - // 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 + protected void addGenericCapability(List<IProvidedCapability> caps, GenericDescription provideCapDesc, InstallableUnitDescription iu, int capNo) { String capNs = provideCapDesc.getType(); + Map<String, Object> capAttrs = new HashMap<>(provideCapDesc.getDeclaredAttributes()); - // Resolve the mandatory p2 name + // Resolve the 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? @@ -351,32 +338,28 @@ 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$ - // Resolve the mandatory p2 version + // 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 // 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( - IProvidedCapability.PROPERTY_VERSION, + CAPABILITY_ATTR_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 33822347f..71288480a 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.isVersionRangeRequirement(requiredCapability.getMatches())) { + if (!RequiredCapability.isSimpleRequirement(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 de1601d90..f1af9f142 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,9 +11,6 @@ *******************************************************************************/ 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 @@ -32,20 +29,7 @@ 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 3a532f6ad..6973a2f06 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.*; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Stack; import org.eclipse.equinox.p2.metadata.Version; public class XMLWriter implements XMLConstants { @@ -220,82 +220,28 @@ public class XMLWriter implements XMLConstants { this.pw.flush(); } - public void writeProperties(Map<String, ?> properties) { + public void writeProperties(Map<String, String> properties) { writeProperties(PROPERTIES_ELEMENT, properties); } - 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, 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$ + 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()); } - - valueStr = coll.stream().map(Object::toString).collect(joining(",")); //$NON-NLS-1$ - } else { - type = resolvePropertyType(value); - valueStr = value.toString(); + end(propertiesElement); } + } + public void writeProperty(String name, String value) { start(PROPERTY_ELEMENT); attribute(PROPERTY_NAME_ATTRIBUTE, name); - attribute(PROPERTY_VALUE_ATTRIBUTE, valueStr); - attributeOptional(PROPERTY_TYPE_ATTRIBUTE, type); + attribute(PROPERTY_VALUE_ATTRIBUTE, value); 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 d726d6a5b..f229b4e66 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,16 +10,14 @@ 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.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.*; import org.eclipse.equinox.p2.metadata.expression.IMatchExpression; import org.eclipse.equinox.p2.tests.AbstractProvisioningTest; @@ -27,6 +25,20 @@ 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 @@ -34,39 +46,26 @@ public class AutomatedDirectorTest extends AbstractProvisioningTest { * and the second IU should not be installed. */ public void testInstallFilteredCapability() { - final String envKey = "filterKey"; - final String envVal = "true"; - - // The IU that is required + //The IU that is required IInstallableUnit requiredIU = createIU("required." + getName()); // The IU to be installed - 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); + 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}); - // Metadata repository IInstallableUnit[] allUnits = new IInstallableUnit[] {requiredIU, toInstallIU}; createTestMetdataRepository(allUnits); + IDirector director = createDirector(); - // Install into a profile in which the requirement filter is satisfied + //Install into a profile in which the filter is satisfied Map<String, String> properties = new HashMap<>(); - properties.put(IProfile.PROP_ENVIRONMENTS, envKey + "=" + envVal); - - // Profile + properties.put(IProfile.PROP_ENVIRONMENTS, "FilterKey=true"); 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(result.isOK()); + assertTrue("1.0", result.isOK()); assertProfileContains("1.1", satisfied, allUnits); } @@ -74,41 +73,25 @@ public class AutomatedDirectorTest extends AbstractProvisioningTest { * Tests installing an IU that has an optional prerequisite that is available. */ public void testInstallOptionalAvailable() { - final String capabilityNamespace = "test.capability"; - final String capabilityName = "test." + getName(); - final Version capabilityVersion = DEFAULT_VERSION; - + String capabilityId = "test." + getName(); //The IU that exports the capability - IProvidedCapability[] provides = new IProvidedCapability[] { - MetadataFactory.createProvidedCapability(capabilityNamespace, capabilityName, capabilityVersion) - }; - IInstallableUnit requiredIU = createIU("required." + getName(), provides); + IInstallableUnit requiredIU = createIU("required." + getName(), new IProvidedCapability[] {MetadataFactory.createProvidedCapability("test.capability", capabilityId, DEFAULT_VERSION)}); //The IU that optionally requires the capability - IRequirement[] requires = new IRequirement[] { - MetadataFactory.createRequirement(capabilityNamespace, capabilityName, ANY_VERSION, null, /* optional=> */true, /* multiple=> */false, /* greedy=>*/false) - }; - IInstallableUnit toInstallIU = createIU("toInstall." + getName(), requires); + IRequirement required = MetadataFactory.createRequirement("test.capability", capabilityId, ANY_VERSION, null, /* optional=> */true, /* multiple=> */false, /* greedy=>*/false); + IInstallableUnit toInstallIU = createIU("toInstall." + getName(), new IRequirement[] {required}); - // Metadata repository IInstallableUnit[] allUnits = new IInstallableUnit[] {toInstallIU, requiredIU}; + IInstallableUnit[] toInstallArray = new IInstallableUnit[] {toInstallIU}; createTestMetdataRepository(allUnits); IProfile profile = createProfile("TestProfile." + getName()); - - // Change request + IDirector director = createDirector(); 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); } @@ -117,34 +100,21 @@ public class AutomatedDirectorTest extends AbstractProvisioningTest { * Tests installing an IU that has an optional prerequisite that is not available. */ public void testInstallOptionalUnavailable() { - 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); + 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}); - // Metadata repo IInstallableUnit[] allUnits = new IInstallableUnit[] {toInstallIU}; createTestMetdataRepository(allUnits); - // Profile IProfile profile = createProfile("TestProfile." + getName()); - - // Change request + IDirector director = createDirector(); 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); } @@ -154,50 +124,30 @@ public class AutomatedDirectorTest extends AbstractProvisioningTest { * the capability has a platform filter that is not satisfied. */ public void testInstallPlatformFilter() { - // 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; - - // The IU that exports the capability - IProvidedCapability[] provides = new IProvidedCapability[] {MetadataFactory.createProvidedCapability(capabilityNamespace, capabilityName, capabilityVersion)}; - IInstallableUnit requiredIU = createIU("required." + getName(), createFilter(osKey, osVal), provides); + //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); - // Installed IU - IInstallableUnit toInstallIU = createIU("toInstall." + getName(), createRequiredCapabilities(capabilityNamespace, capabilityName, ANY_VERSION, (IMatchExpression<IInstallableUnit>) null)); + IInstallableUnit toInstallIU = createIU("toInstall." + getName(), createRequiredCapabilities("test.capability", capabilityId, ANY_VERSION, (IMatchExpression<IInstallableUnit>) null)); - // Metadata repo IInstallableUnit[] allUnits = new IInstallableUnit[] {requiredIU, toInstallIU}; + IInstallableUnit[] toInstallArray = new IInstallableUnit[] {toInstallIU}; createTestMetdataRepository(allUnits); - IDirector director = createDirector(); - - // Profile that does not satisfy the OS requirement IProfile profile = createProfile("TestProfile." + getName()); - - // Request + IDirector director = createDirector(); 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()); - // New profile that satisfies the OS requirement + //try again with the filter satisfied Map<String, String> properties = new HashMap<>(); - properties.put(IProfile.PROP_ENVIRONMENTS, osKey + "=" + osVal); - profile = createProfile("TestProfile2." + getName(), properties); - - // New request - request = new ProfileChangeRequest(profile); + properties.put(IProfile.PROP_ENVIRONMENTS, "osgi.os=blort"); + IProfile profile2 = createProfile("TestProfile2." + getName(), properties); + request = new ProfileChangeRequest(profile2); request.addInstallableUnits(toInstallArray); - - // New provisioning - should succeed result = director.provision(request, null, null); assertTrue("2.0", result.isOK()); } @@ -206,42 +156,27 @@ public class AutomatedDirectorTest extends AbstractProvisioningTest { * Tests installing an IU that has an unsatisfied platform filter */ public void testInstallPlatformFilterUnsatisfied() { - // 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 + //The IU to install + IInstallableUnit toInstallIU = createIU("toInstall." + getName(), createFilter("osgi.os", "blort"), NO_PROVIDES); IInstallableUnit[] allUnits = new IInstallableUnit[] {toInstallIU}; + IInstallableUnit[] toInstallArray = new IInstallableUnit[] {toInstallIU}; createTestMetdataRepository(allUnits); - // Profile without a matching environment IProfile profile = createProfile("TestProfile." + getName()); - - // Change request + IDirector director = createDirector(); 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(!result.isOK()); + assertTrue("1.0", !result.isOK()); - // Profile with matching environment + //try again with the filter satisfied Map<String, String> properties = new HashMap<>(); - properties.put(IProfile.PROP_ENVIRONMENTS, osKey + "=" + osVal); - profile = createProfile("TestProfile2." + getName(), properties); - - // New change request - request = new ProfileChangeRequest(profile); + properties.put(IProfile.PROP_ENVIRONMENTS, "osgi.os=blort"); + IProfile profile2 = createProfile("TestProfile2." + getName(), properties); + request = new ProfileChangeRequest(profile2); request.addInstallableUnits(toInstallArray); - - // Provisioning success result = director.provision(request, null, null); - assertTrue(result.isOK()); + assertTrue("2.0", result.isOK()); } /** @@ -249,39 +184,24 @@ public class AutomatedDirectorTest extends AbstractProvisioningTest { * that the IU providing the capability is installed. */ public void testSimpleInstallRequired() { - // Test capability - String capabilityNamespace = "test.capability"; - String capabilityName = "test." + getName(); - + String capabilityId = "test." + getName(); //The IU that exports the capability - IProvidedCapability[] provides = new IProvidedCapability[] { - MetadataFactory.createProvidedCapability(capabilityNamespace, capabilityName, DEFAULT_VERSION) - }; - IInstallableUnit requiredIU = createIU("required." + getName(), provides); + IInstallableUnit requiredIU = createIU("required." + getName(), new IProvidedCapability[] {MetadataFactory.createProvidedCapability("test.capability", capabilityId, DEFAULT_VERSION)}); - // The IU that requires the capability - IRequirement[] requires = createRequiredCapabilities(capabilityNamespace, capabilityName, ANY_VERSION, (IMatchExpression<IInstallableUnit>) null); - IInstallableUnit toInstallIU = createIU("toInstall." + getName(), requires); + IInstallableUnit toInstallIU = createIU("toInstall." + getName(), createRequiredCapabilities("test.capability", capabilityId, ANY_VERSION, (IMatchExpression<IInstallableUnit>) null)); - // Crate the metadata repo IInstallableUnit[] allUnits = new IInstallableUnit[] {requiredIU, toInstallIU}; + IInstallableUnit[] toInstallArray = new IInstallableUnit[] {toInstallIU}; createTestMetdataRepository(allUnits); - // Provision IProfile profile = createProfile("TestProfile." + getName()); - // Create the profile change request + IDirector director = createDirector(); 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); } @@ -291,34 +211,24 @@ 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()); - // 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); + IRequirement capability = MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, requiredIU.getId(), null, null, false, false); + IInstallableUnit toInstallIU = createIU("toInstall." + getName(), new IRequirement[] {capability}); - // Metadata repo IInstallableUnit[] allUnits = new IInstallableUnit[] {requiredIU, toInstallIU}; + IInstallableUnit[] toInstallArray = new IInstallableUnit[] {toInstallIU}; createTestMetdataRepository(allUnits); - // Profile IProfile profile = createProfile("TestProfile." + getName()); - // Profile change request + IDirector director = createDirector(); 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); } @@ -329,34 +239,25 @@ public class AutomatedDirectorTest extends AbstractProvisioningTest { * capability on the IU namespace. */ public void testSimpleInstallRequiredIU() { - // The IU that is required. It exports it's identity capability by default. + //The IU that exports the capability IInstallableUnit requiredIU = createIU("required." + getName()); - // 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); + IRequirement capability = MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, requiredIU.getId(), ANY_VERSION, null, false, false); + IInstallableUnit toInstallIU = createIU("toInstall." + getName(), new IRequirement[] {capability}); - // Create the metadata repo IInstallableUnit[] allUnits = new IInstallableUnit[] {requiredIU, toInstallIU}; + IInstallableUnit[] toInstallArray = new IInstallableUnit[] {toInstallIU}; createTestMetdataRepository(allUnits); IProfile profile = createProfile("TestProfile." + getName()); - // Create the profile change request + IDirector director = createDirector(); 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(result.isOK()); + assertTrue("1.0", 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 609d1d69a..f085f9415 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,42 +12,21 @@ package org.eclipse.equinox.p2.tests.engine; import java.io.File; import java.net.URI; -import java.util.EventObject; -import java.util.HashMap; -import java.util.Map; +import java.util.*; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -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.*; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest; -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.engine.*; 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.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.engine.*; import org.eclipse.equinox.p2.metadata.IInstallableUnit; -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.query.*; import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository; import org.eclipse.equinox.p2.tests.AbstractProvisioningTest; import org.eclipse.equinox.p2.tests.TestActivator; @@ -197,7 +176,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(15, TimeUnit.SECONDS); + listener.latch.await(10, 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 476d0daed..1ccc188bf 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,23 +23,18 @@ 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()); - } - - public void testPropertiesRequirement() { - IRequirement req = MetadataFactory.createRequirement("expectedNameSpace", "(key=val)", null, 1, 1, true); - assertEquals("expectedNameSpace; (key=val)", req.toString()); + assertEquals("expectedNameSpace expectedName [1.0.0,2.0.0)", 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 8e5be56d7..27ebc00b8 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,16 +4,13 @@ * 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.JUnit4TestAdapter; -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; +import junit.framework.*; /** * Performs all automated director tests. @@ -23,7 +20,7 @@ public class AllTests extends TestCase { public static Test suite() { TestSuite suite = new TestSuite(AllTests.class.getName()); suite.addTestSuite(ExpressionTest.class); - suite.addTest(new JUnit4TestAdapter(FilterTest.class)); + suite.addTestSuite(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 4a51833fb..0d6895ac2 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,225 +10,19 @@ *******************************************************************************/ 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.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); - } - } +import java.util.*; +import junit.framework.*; +import org.eclipse.equinox.p2.metadata.expression.*; +import org.osgi.framework.*; +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; @@ -248,17 +42,17 @@ public class FilterTest { } 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++) { @@ -269,25 +63,230 @@ public class FilterTest { } 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 605143491..022b6549f 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> properties; + private final Map<String, Object> attributes; public SPIProvidedCapability(String namespace, String name, Version version) { this.namespace = namespace; - this.properties = new HashMap<>(); - properties.put(namespace, name); - properties.put(IProvidedCapability.PROPERTY_VERSION, version); + this.attributes = new HashMap<>(); + attributes.put(namespace, name); + attributes.put(ProvidedCapability.ATTRIBUTE_VERSION, version); } @Override @@ -199,7 +199,7 @@ public class SPIMetadataRepositoryTest extends AbstractProvisioningTest { if (!(namespace.equals(otherCapability.getNamespace()))) { return false; } - if (!(properties.equals(otherCapability.getProperties()))) { + if (!(attributes.equals(otherCapability.getAttributes()))) { return false; } return true; @@ -207,12 +207,12 @@ public class SPIMetadataRepositoryTest extends AbstractProvisioningTest { @Override public String toString() { - return namespace + "; " + properties; + return namespace + "; " + attributes; } @Override public String getName() { - return (String) properties.get(namespace); + return (String) attributes.get(namespace); } @Override @@ -222,12 +222,12 @@ public class SPIMetadataRepositoryTest extends AbstractProvisioningTest { @Override public Version getVersion() { - return (Version) properties.get(IProvidedCapability.PROPERTY_VERSION); + return (Version) attributes.get(ProvidedCapability.ATTRIBUTE_VERSION); } @Override - public Map<String, Object> getProperties() { - return Collections.unmodifiableMap(properties); + public Map<String, Object> getAttributes() { + return Collections.unmodifiableMap(attributes); } } 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 deleted file mode 100644 index 4d709c93a..000000000 --- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/PropertyMatchRequirement.java +++ /dev/null @@ -1,111 +0,0 @@ -/******************************************************************************* - * 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 faf51598b..058cca76c 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,13 +27,15 @@ 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; @@ -90,25 +92,18 @@ 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 envFilter, int minCard, int maxCard, boolean greedy) { - IRequirement expected = MetadataFactory.createRequirement(namespace, name, range, InstallableUnit.parseFilter(envFilter), minCard, maxCard, greedy); + 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); verifyRequirement(actual, expected); } - 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); + 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); 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 7e3ab0344..af99bfe42 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,19 +77,18 @@ 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 = "(|(&(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 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 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 = JAVA_EE_1_4; + private static final String TEST1_REQ_EE_FILTER = JAVA_EE_1_4_REQ; 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 = JAVA_EE_1_4; + private static final String TEST2_REQ_EE_FILTER = JAVA_EE_1_4_REQ; 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$ @@ -100,9 +99,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 = JAVA_EE_1_4; + private static final String TEST5_REQ_EE_FILTER = JAVA_EE_1_4_REQ; private static final String TEST5_PROV_BUNDLE_NAME = "test5";//$NON-NLS-1$ - private static final String TESTDYN_REQ_EE = JAVA_EE_1_6; + private static final String TESTDYN_REQ_EE_FILTER = JAVA_EE_1_6_REQ; 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); @@ -174,32 +173,32 @@ public class BundlesActionTest extends ActionTest { bundlesAction.perform(info, results, new NullProgressMonitor()); Collection<IInstallableUnit> ius = results.getIUs(null, null); - assertEquals(1, ius.size()); + assertEquals("1.0", 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(1, ius.size()); + assertEquals("2.0", 1, ius.size()); QueryableArray queryableArray = new QueryableArray(ius.toArray(new IInstallableUnit[ius.size()])); IQueryResult<IInstallableUnit> result = queryableArray.query(QueryUtil.createIUQuery("foo"), null); - assertEquals(1, queryResultSize(result)); + assertEquals("3.1", 1, queryResultSize(result)); IInstallableUnit iu = result.iterator().next(); TranslationSupport utils = new TranslationSupport(); utils.setTranslationSource(queryableArray); - assertEquals("English Foo", utils.getIUProperty(iu, IInstallableUnit.PROP_NAME)); + assertEquals("3.2", "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(3, ius.size()); + assertEquals("2.0", 3, ius.size()); queryableArray = new QueryableArray(ius.toArray(new IInstallableUnit[ius.size()])); result = queryableArray.query(QueryUtil.createIUQuery("foo"), null); - assertEquals(1, queryResultSize(result)); + assertEquals("2.1", 1, queryResultSize(result)); iu = result.iterator().next(); utils.setTranslationSource(queryableArray); - assertEquals("German Foo", utils.getIUProperty(iu, IInstallableUnit.PROP_NAME, Locale.GERMAN.toString())); + assertEquals("2.2", "German Foo", utils.getIUProperty(iu, IInstallableUnit.PROP_NAME, Locale.GERMAN.toString())); } private void verifyBundlesAction() throws Exception { @@ -218,7 +217,7 @@ public class BundlesActionTest extends ActionTest { IArtifactDescriptor[] descriptors = artifactRepository.getArtifactDescriptors(key2); // Should have one canonical and one packed - assertEquals(2, descriptors.length); + assertTrue("1.0", descriptors.length == 2); int packedIdx; int canonicalIdx; @@ -245,18 +244,18 @@ public class BundlesActionTest extends ActionTest { } private void verifyBundle1() { - List<IInstallableUnit> ius = new ArrayList<>(publisherResult.getIUs(TEST1_PROVBUNDLE_NAME, IPublisherResult.ROOT)); - assertEquals(1, ius.size()); + ArrayList<IInstallableUnit> ius = new ArrayList<>(publisherResult.getIUs(TEST1_PROVBUNDLE_NAME, IPublisherResult.ROOT)); + assertTrue(ius.size() == 1); IInstallableUnit bundle1IU = ius.get(0); - assertNotNull(bundle1IU); - assertEquals(bundle1IU.getVersion(), BUNDLE1_VERSION); + assertNotNull("1.0", bundle1IU); + assertEquals("1.1", bundle1IU.getVersion(), BUNDLE1_VERSION); // check required capabilities - 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()); + 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()); // check provided capabilities Collection<IProvidedCapability> providedCapabilities = bundle1IU.getProvidedCapabilities(); @@ -265,7 +264,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(5, providedCapabilities.size()); + assertEquals("2.1", 5, providedCapabilities.size()); Collection<ITouchpointData> data = bundle1IU.getTouchpointData(); boolean found = false; @@ -278,27 +277,27 @@ public class BundlesActionTest extends ActionTest { found = true; } } - assertTrue(found); + assertTrue("3.0", found); } private void verifyBundle2() { - List<IInstallableUnit> ius = new ArrayList<>(publisherResult.getIUs(TEST2_PROV_BUNDLE_NAME, IPublisherResult.ROOT)); - assertEquals(1, ius.size()); + ArrayList<IInstallableUnit> ius = new ArrayList<>(publisherResult.getIUs(TEST2_PROV_BUNDLE_NAME, IPublisherResult.ROOT)); + assertTrue(ius.size() == 1); + IInstallableUnit bundle2IU = ius.get(0); - IInstallableUnit bundleIu = ius.get(0); - assertNotNull(bundleIu); - assertEquals(bundleIu.getVersion(), BUNDLE2_VERSION); + assertNotNull(bundle2IU); + assertEquals(bundle2IU.getVersion(), BUNDLE2_VERSION); // check required capabilities - Collection<IRequirement> requirements = bundleIu.getRequirements(); + Collection<IRequirement> requirements = bundle2IU.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, OSGI_EE, TEST2_REQ_EE, null, 1, 1, true); - assertEquals(4, requirements.size()); + verifyRequirement(requirements, TEST2_REQ_EE_FILTER, 0, 1, true); + assertTrue(requirements.size() == 4 /*number of tested elements*/); // check provided capabilities - Collection<IProvidedCapability> providedCapabilities = bundleIu.getProvidedCapabilities(); + Collection<IProvidedCapability> providedCapabilities = bundle2IU.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); @@ -309,11 +308,11 @@ public class BundlesActionTest extends ActionTest { assertEquals(7, providedCapabilities.size()); /*number of tested elements*/ // check %bundle name is correct - Map<String, String> prop = bundleIu.getProperties(); + Map<String, String> prop = bundle2IU.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 = bundleIu.getTouchpointData(); + Collection<ITouchpointData> data = bundle2IU.getTouchpointData(); boolean found = false; for (ITouchpointData td : data) { ITouchpointInstruction configure = td.getInstruction("configure"); @@ -324,17 +323,18 @@ public class BundlesActionTest extends ActionTest { found = true; } } - assertFalse(found); + assertFalse("3.0", 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()); - IInstallableUnit bundleIu = ius.get(0); + assertTrue(ius.size() == 1); + IInstallableUnit bundle3IU = ius.get(0); - IUpdateDescriptor updateDescriptor = bundleIu.getUpdateDescriptor(); + IUpdateDescriptor updateDescriptor = bundle3IU.getUpdateDescriptor(); String name = RequiredCapability.extractName(updateDescriptor.getIUsBeingUpdated().iterator().next()); VersionRange range = RequiredCapability.extractRange(updateDescriptor.getIUsBeingUpdated().iterator().next()); String description = updateDescriptor.getDescription(); @@ -349,31 +349,36 @@ public class BundlesActionTest extends ActionTest { private void verifyBundle4() { ArrayList<IInstallableUnit> ius = new ArrayList<>(publisherResult.getIUs(TEST4_PROV_BUNDLE_NAME, IPublisherResult.ROOT)); - assertEquals(1, ius.size()); + assertTrue(ius.size() == 1); + IInstallableUnit bundle4IU = ius.get(0); - IInstallableUnit bundleIu = ius.get(0); - assertNotNull(bundleIu); - assertEquals(bundleIu.getVersion(), BUNDLE4_VERSION); + assertNotNull("1.0", bundle4IU); + assertEquals("1.1", bundle4IU.getVersion(), BUNDLE4_VERSION); // check required capabilities - Collection<IRequirement> requirements = bundleIu.getRequirements(); + Collection<IRequirement> requirements = bundle4IU.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(4, requirements.size()); + assertEquals("2.0", 4, requirements.size()); } private void verifyBundle5() { ArrayList<IInstallableUnit> ius = new ArrayList<>(publisherResult.getIUs(TEST5_PROV_BUNDLE_NAME, IPublisherResult.ROOT)); - assertEquals(1, ius.size()); - + assertTrue(ius.size() == 1); IInstallableUnit bundle5IU = ius.get(0); Collection<IRequirement> requirements = bundle5IU.getRequirements(); - 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()); + 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); } @Override @@ -486,7 +491,7 @@ public class BundlesActionTest extends ActionTest { IInstallableUnit iu = BundlesAction.createBundleIU(BundlesAction.createBundleDescription(testData), null, new PublisherInfo()); Collection<IRequirement> requirements = iu.getRequirements(); - verifyRequirement(requirements, OSGI_EE, TESTDYN_REQ_EE, null, 1, 1, true); + verifyRequirement(requirements, TESTDYN_REQ_EE_FILTER, 0, 1, true); assertEquals(1, requirements.size()); } |