| /******************************************************************************* |
| * Copyright (c) 2009, 2020 IBM Corporation and others. |
| * |
| * This |
| * program and the accompanying materials are made available under the terms of |
| * the Eclipse Public License 2.0 which accompanies this distribution, and is |
| * available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: IBM Corporation - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.equinox.p2.publisher; |
| |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.util.*; |
| import java.util.Map.Entry; |
| import org.eclipse.equinox.internal.p2.metadata.ArtifactKey; |
| import org.eclipse.equinox.internal.p2.metadata.InstallableUnit; |
| 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.expression.*; |
| import org.eclipse.equinox.spi.p2.publisher.PublisherHelper; |
| |
| public class AdviceFileParser { |
| |
| private static final String ADVICE_VERSION = "advice.version"; //$NON-NLS-1$ |
| |
| private static final String QUALIFIER_SUBSTITUTION = "$qualifier$"; //$NON-NLS-1$ |
| private static final String VERSION_SUBSTITUTION = "$version$"; //$NON-NLS-1$ |
| |
| private static final String UPDATE_DESCRIPTION = "update.description"; //$NON-NLS-1$ |
| private static final String UPDATE_SEVERITY = "update.severity"; //$NON-NLS-1$ |
| private static final String UPDATE_RANGE = "update.range"; //$NON-NLS-1$ |
| private static final String UPDATE_ID = "update.id"; //$NON-NLS-1$ |
| private static final String UPDATE_MATCH_EXP = "update.matchExp"; //$NON-NLS-1$ |
| private static final String CLASSIFIER = "classifier"; //$NON-NLS-1$ |
| private static final String TOUCHPOINT_VERSION = "touchpoint.version"; //$NON-NLS-1$ |
| private static final String TOUCHPOINT_ID = "touchpoint.id"; //$NON-NLS-1$ |
| private static final String COPYRIGHT_LOCATION = "copyright.location"; //$NON-NLS-1$ |
| private static final String COPYRIGHT = "copyright"; //$NON-NLS-1$ |
| private static final String ID = "id"; //$NON-NLS-1$ |
| private static final String SINGLETON = "singleton"; //$NON-NLS-1$ |
| private static final String IMPORT = "import"; //$NON-NLS-1$ |
| private static final String RANGE = "range"; //$NON-NLS-1$ |
| private static final String MIN = "min"; //$NON-NLS-1$ |
| private static final String MAX = "max"; //$NON-NLS-1$ |
| private static final String FILTER = "filter"; //$NON-NLS-1$ |
| private static final String MULTIPLE = "multiple"; //$NON-NLS-1$ |
| private static final String OPTIONAL = "optional"; //$NON-NLS-1$ |
| private static final String GREEDY = "greedy"; //$NON-NLS-1$ |
| private static final String VERSION = "version"; //$NON-NLS-1$ |
| private static final String NAMESPACE = "namespace"; //$NON-NLS-1$ |
| private static final String NAME = "name"; //$NON-NLS-1$ |
| private static final String MATCH_EXP = "matchExp"; //$NON-NLS-1$ |
| private static final String LOCATION = "location"; //$NON-NLS-1$ |
| private static final String VALUE = "value"; //$NON-NLS-1$ |
| |
| private static final String UNITS_PREFIX = "units."; //$NON-NLS-1$ |
| private static final String INSTRUCTIONS_PREFIX = "instructions."; //$NON-NLS-1$ |
| private static final String REQUIRES_PREFIX = "requires."; //$NON-NLS-1$ |
| private static final String META_REQUIREMENTS_PREFIX = "metaRequirements."; //$NON-NLS-1$ |
| private static final String PROVIDES_PREFIX = "provides."; //$NON-NLS-1$ |
| private static final String PROPERTIES_PREFIX = "properties."; //$NON-NLS-1$ |
| private static final String LICENSES_PREFIX = "licenses."; //$NON-NLS-1$ |
| private static final String ARTIFACTS_PREFIX = "artifacts."; //$NON-NLS-1$ |
| private static final String HOST_REQUIREMENTS_PREFIX = "hostRequirements."; //$NON-NLS-1$ |
| private static final String UPDATE_DESCRIPTOR_PREFIX = "update."; //$NON-NLS-1$ |
| |
| public static final Version COMPATIBLE_VERSION = Version.createOSGi(1, 0, 0); |
| public static final VersionRange VERSION_TOLERANCE = new VersionRange(COMPATIBLE_VERSION, true, |
| Version.createOSGi(2, 0, 0), false); |
| |
| private Map<String, String> adviceProperties = new HashMap<>(); |
| private List<IProvidedCapability> adviceProvides = new ArrayList<>(); |
| private List<IRequirement> adviceRequires = new ArrayList<>(); |
| private List<IRequirement> adviceMetaRequires = new ArrayList<>(); |
| private IUpdateDescriptor adviceUpdateDescriptor = null; |
| private Map<String, ITouchpointInstruction> adviceInstructions = new HashMap<>(); |
| private List<InstallableUnitDescription> adviceOtherIUs = new ArrayList<>(); |
| |
| private final Map<String, String> advice; |
| private Iterator<String> keysIterator; |
| private String current; |
| private String hostId; |
| private Version hostVersion; |
| |
| public AdviceFileParser(String id, Version version, Map<String, String> advice) { |
| this.hostId = id; |
| this.hostVersion = version; |
| this.advice = advice; |
| } |
| |
| public void parse() { |
| String adviceVersion = advice.get(ADVICE_VERSION); |
| if (adviceVersion != null) |
| checkAdviceVersion(adviceVersion); |
| |
| List<String> keys = new ArrayList<>(advice.keySet()); |
| keys.sort(null); |
| |
| keysIterator = keys.iterator(); |
| next(); |
| |
| while (current != null) { |
| if (current.startsWith(PROPERTIES_PREFIX)) |
| parseProperties(PROPERTIES_PREFIX, adviceProperties); |
| else if (current.startsWith(UPDATE_DESCRIPTOR_PREFIX)) |
| this.adviceUpdateDescriptor = parseUpdateDescriptor(UPDATE_DESCRIPTOR_PREFIX, hostId); |
| else if (current.startsWith(PROVIDES_PREFIX)) |
| parseProvides(PROVIDES_PREFIX, adviceProvides); |
| else if (current.startsWith(REQUIRES_PREFIX)) |
| parseRequires(REQUIRES_PREFIX, adviceRequires); |
| else if (current.startsWith(META_REQUIREMENTS_PREFIX)) |
| parseRequires(META_REQUIREMENTS_PREFIX, adviceMetaRequires); |
| else if (current.startsWith(INSTRUCTIONS_PREFIX)) |
| parseInstructions(INSTRUCTIONS_PREFIX, adviceInstructions); |
| else if (current.startsWith(UNITS_PREFIX)) |
| parseUnits(UNITS_PREFIX, adviceOtherIUs); |
| else if (current.equals(ADVICE_VERSION)) { |
| next(); |
| } else { |
| // we ignore elements we do not understand |
| next(); |
| } |
| } |
| } |
| |
| private void checkAdviceVersion(String adviceVersion) { |
| Version version = Version.parseVersion(adviceVersion); |
| if (!VERSION_TOLERANCE.isIncluded(version)) |
| throw new IllegalStateException("bad version: " + version + ". Expected range was " + VERSION_TOLERANCE); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| private void next() { |
| current = keysIterator.hasNext() ? keysIterator.next() : null; |
| } |
| |
| private String currentValue() { |
| return advice.get(current).trim(); |
| } |
| |
| private void parseProperties(String prefix, Map<String, String> properties) { |
| while (current != null && current.startsWith(prefix)) { |
| int dotIndex = current.indexOf('.', prefix.length()); |
| if (dotIndex == -1) |
| throw new IllegalStateException("bad token: " + current); //$NON-NLS-1$ |
| |
| parseProperty(current.substring(0, dotIndex + 1), properties); |
| } |
| } |
| |
| private void parseProperty(String prefix, Map<String, String> properties) { |
| String propertyName = null; |
| String propertyValue = null; |
| while (current != null && current.startsWith(prefix)) { |
| String token = current.substring(prefix.length()); |
| switch (token) { |
| case NAME: |
| propertyName = currentValue(); |
| break; |
| case VALUE: |
| propertyValue = currentValue(); |
| break; |
| // we ignore elements we do not understand |
| default: |
| break; |
| } |
| next(); |
| } |
| |
| properties.put(propertyName, propertyValue); |
| } |
| |
| private IUpdateDescriptor parseUpdateDescriptor(String prefix, String id) { |
| String name = id; |
| String description = null; |
| String range = "[0.0.0,$version$)"; //$NON-NLS-1$ |
| String severity = "0"; //$NON-NLS-1$ |
| String match = null; |
| |
| while (current != null && current.startsWith(prefix)) { |
| String token = current; |
| switch (token) { |
| case UPDATE_MATCH_EXP: |
| match = currentValue(); |
| break; |
| case UPDATE_ID: |
| name = currentValue(); |
| break; |
| case UPDATE_DESCRIPTION: |
| description = currentValue(); |
| break; |
| case UPDATE_RANGE: |
| range = currentValue(); |
| break; |
| case UPDATE_SEVERITY: |
| severity = currentValue(); |
| break; |
| // ignore |
| default: |
| break; |
| } |
| next(); |
| } |
| |
| if (match != null) { |
| // When update.match is specified, versionRange and id are ignored |
| IExpression expr = ExpressionUtil.parse(substituteVersionAndQualifier(match)); |
| IMatchExpression<IInstallableUnit> matchExpression = ExpressionUtil.getFactory().matchExpression(expr); |
| Collection<IMatchExpression<IInstallableUnit>> descriptors = new ArrayList<>(1); |
| descriptors.add(matchExpression); |
| return MetadataFactory.createUpdateDescriptor(descriptors, Integer.valueOf(severity), description, |
| (URI) null); |
| } |
| range = substituteVersionAndQualifier(range); |
| VersionRange versionRange = VersionRange.create(range); |
| return MetadataFactory.createUpdateDescriptor(name, versionRange, Integer.valueOf(severity), description); |
| } |
| |
| private void parseProvides(String prefix, List<IProvidedCapability> provides) { |
| while (current != null && current.startsWith(prefix)) { |
| int dotIndex = current.indexOf('.', prefix.length()); |
| if (dotIndex == -1) |
| throw new IllegalStateException("bad token: " + current); //$NON-NLS-1$ |
| |
| parseProvided(current.substring(0, dotIndex + 1), provides); |
| } |
| } |
| |
| private void parseProvided(String prefix, List<IProvidedCapability> provides) { |
| String namespace = null; |
| String name = null; |
| Version capabilityVersion = null; |
| while (current != null && current.startsWith(prefix)) { |
| String token = current.substring(prefix.length()); |
| switch (token) { |
| case NAME: |
| name = currentValue(); |
| break; |
| case NAMESPACE: |
| namespace = currentValue(); |
| break; |
| case VERSION: |
| capabilityVersion = Version.parseVersion(substituteVersionAndQualifier(currentValue())); |
| break; |
| // we ignore elements we do not understand |
| default: |
| break; |
| } |
| next(); |
| } |
| |
| IProvidedCapability capability = MetadataFactory.createProvidedCapability(namespace, name, capabilityVersion); |
| provides.add(capability); |
| } |
| |
| private void parseRequires(String prefix, List<IRequirement> requires) { |
| while (current != null && current.startsWith(prefix)) { |
| int dotIndex = current.indexOf('.', prefix.length()); |
| if (dotIndex == -1) |
| throw new IllegalStateException("bad token: " + current); //$NON-NLS-1$ |
| |
| parseRequired(current.substring(0, dotIndex + 1), requires); |
| } |
| } |
| |
| private void parseRequired(String prefix, List<IRequirement> requires) { |
| |
| String namespace = null; |
| String name = null; |
| VersionRange range = null; |
| String matchExp = null; |
| String filter = null; |
| boolean optional = false; |
| boolean multiple = false; |
| boolean greedy = true; |
| |
| int min = -1; |
| int max = -1; |
| |
| while (current != null && current.startsWith(prefix)) { |
| String token = current.substring(prefix.length()); |
| switch (token) { |
| case GREEDY: |
| greedy = Boolean.parseBoolean(currentValue()); |
| break; |
| case OPTIONAL: |
| optional = Boolean.parseBoolean(currentValue()); |
| break; |
| case MULTIPLE: |
| multiple = Boolean.parseBoolean(currentValue()); |
| break; |
| case FILTER: |
| filter = currentValue(); |
| break; |
| case NAME: |
| name = currentValue(); |
| break; |
| case NAMESPACE: |
| namespace = currentValue(); |
| break; |
| case RANGE: |
| range = VersionRange.create(substituteVersionAndQualifier(currentValue())); |
| break; |
| case MIN: |
| min = Integer.valueOf(currentValue()).intValue(); |
| break; |
| case MAX: |
| max = Integer.valueOf(currentValue()).intValue(); |
| break; |
| case MATCH_EXP: |
| matchExp = currentValue(); |
| break; |
| // we ignore elements we do not understand |
| default: |
| break; |
| } |
| next(); |
| } |
| IRequirement capability = null; |
| if (matchExp == null) { |
| if (min >= 0 && max >= 0) { |
| capability = createRequirement(namespace, name, range, filter, min, max, greedy); |
| } else { |
| capability = createRequirement(namespace, name, range, filter, optional, multiple, greedy); |
| } |
| } else { |
| // When a match expression is specified, namespace, name and versionRange are |
| // ignored |
| if (optional && min == -1 && max == -1) { |
| min = 0; |
| max = 1; |
| } |
| capability = createRequirement(matchExp, filter, min, max, greedy, null); |
| } |
| if (capability != null) { |
| requires.add(capability); |
| } |
| } |
| |
| protected IRequirement createRequirement(String requirement, String filter, int min, int max, boolean greedy, |
| String description) { |
| IExpression expr = ExpressionUtil.parse(substituteVersionAndQualifier(requirement)); |
| IMatchExpression<IInstallableUnit> requirementExp = ExpressionUtil.getFactory().matchExpression(expr); |
| IMatchExpression<IInstallableUnit> filterExp = InstallableUnit.parseFilter(filter); |
| return MetadataFactory.createRequirement(requirementExp, filterExp, min, max, greedy, description); |
| } |
| |
| protected IRequirement createRequirement(String namespace, String name, VersionRange range, String filter, int min, |
| int max, boolean greedy) { |
| IMatchExpression<IInstallableUnit> filterExpression = InstallableUnit.parseFilter(filter); |
| return MetadataFactory.createRequirement(namespace, name, range, filterExpression, min, max, greedy); |
| } |
| |
| protected IRequirement createRequirement(String namespace, String name, VersionRange range, String filter, |
| boolean optional, boolean multiple, boolean greedy) { |
| return MetadataFactory.createRequirement(namespace, name, range, filter, optional, multiple, greedy); |
| } |
| |
| private void parseInstructions(String prefix, Map<String, ITouchpointInstruction> instructions) { |
| while (current != null && current.startsWith(prefix)) { |
| int dotIndex = current.indexOf('.', prefix.length()); |
| if (dotIndex != -1) |
| throw new IllegalStateException("bad token: " + current); //$NON-NLS-1$ |
| |
| parseInstruction(current, instructions); |
| } |
| } |
| |
| private void parseInstruction(String prefix, Map<String, ITouchpointInstruction> instructions) { |
| String phase = current.substring(current.lastIndexOf('.') + 1); |
| String body = currentValue(); |
| next(); |
| |
| prefix += '.'; |
| String importAttribute = null; |
| if (current != null && current.startsWith(prefix)) { |
| if (current.substring(prefix.length()).equals(IMPORT)) { |
| importAttribute = currentValue(); |
| } else { |
| // we ignore elements we do not understand |
| } |
| next(); |
| } |
| ITouchpointInstruction instruction = MetadataFactory.createTouchpointInstruction(body, importAttribute); |
| instructions.put(phase, instruction); |
| } |
| |
| private void parseUnits(String prefix, List<InstallableUnitDescription> ius) { |
| while (current != null && current.startsWith(prefix)) { |
| int dotIndex = current.indexOf('.', prefix.length()); |
| if (dotIndex == -1) |
| throw new IllegalStateException("bad token: " + current + " = " + currentValue()); //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| parseUnit(current.substring(0, dotIndex + 1), ius); |
| } |
| } |
| |
| private void parseUnit(String prefix, List<InstallableUnitDescription> units) { |
| String unitId = null; |
| Version unitVersion = null; |
| boolean unitSingleton = false; |
| String unitFilter = null; |
| String unitCopyright = null; |
| String unitCopyrightLocation = null; |
| String unitTouchpointId = null; |
| Version unitTouchpointVersion = null; |
| |
| String unitUpdateId = null; |
| VersionRange unitUpdateRange = null; |
| int unitUpdateSeverity = 0; |
| String unitUpdateDescription = null; |
| |
| List<IArtifactKey> unitArtifacts = new ArrayList<>(); |
| Map<String, String> unitProperties = new HashMap<>(); |
| List<IRequirement> unitHostRequirements = new ArrayList<>(); |
| List<IProvidedCapability> unitProvides = new ArrayList<>(); |
| List<IRequirement> unitRequires = new ArrayList<>(); |
| List<IRequirement> unitMetaRequirements = new ArrayList<>(); |
| List<ILicense> unitLicenses = new ArrayList<>(); |
| Map<String, ITouchpointInstruction> unitInstructions = new HashMap<>(); |
| // updatedescriptor ?? |
| |
| while (current != null && current.startsWith(prefix)) { |
| String token = current.substring(prefix.length()); |
| if (token.equals(ID)) { |
| unitId = currentValue(); |
| next(); |
| } else if (token.equals(VERSION)) { |
| unitVersion = Version.parseVersion(substituteVersionAndQualifier(currentValue())); |
| next(); |
| } else if (token.equals(SINGLETON)) { |
| unitSingleton = Boolean.parseBoolean(currentValue()); |
| next(); |
| } else if (token.equals(FILTER)) { |
| unitFilter = currentValue(); |
| next(); |
| } else if (token.equals(COPYRIGHT)) { |
| unitCopyright = currentValue(); |
| next(); |
| } else if (token.equals(COPYRIGHT_LOCATION)) { |
| unitCopyrightLocation = currentValue(); |
| next(); |
| } else if (token.equals(TOUCHPOINT_ID)) { |
| unitTouchpointId = currentValue(); |
| next(); |
| } else if (token.equals(TOUCHPOINT_VERSION)) { |
| unitTouchpointVersion = Version.parseVersion(substituteVersionAndQualifier(currentValue())); |
| next(); |
| } else if (token.equals(UPDATE_ID)) { |
| unitUpdateId = currentValue(); |
| next(); |
| } else if (token.equals(UPDATE_RANGE)) { |
| unitUpdateRange = VersionRange.create(substituteVersionAndQualifier(currentValue())); |
| next(); |
| } else if (token.equals(UPDATE_SEVERITY)) { |
| unitUpdateSeverity = Integer.parseInt(currentValue()); |
| next(); |
| } else if (token.equals(UPDATE_DESCRIPTION)) { |
| unitUpdateDescription = currentValue(); |
| next(); |
| } else if (token.startsWith(HOST_REQUIREMENTS_PREFIX)) |
| parseRequires(prefix + HOST_REQUIREMENTS_PREFIX, unitHostRequirements); |
| else if (token.startsWith(ARTIFACTS_PREFIX)) |
| parseArtifacts(prefix + ARTIFACTS_PREFIX, unitArtifacts); |
| else if (token.startsWith(LICENSES_PREFIX)) |
| parseLicenses(prefix + LICENSES_PREFIX, unitLicenses); |
| else if (token.startsWith(PROPERTIES_PREFIX)) |
| parseProperties(prefix + PROPERTIES_PREFIX, unitProperties); |
| else if (token.startsWith(PROVIDES_PREFIX)) |
| parseProvides(prefix + PROVIDES_PREFIX, unitProvides); |
| else if (token.startsWith(REQUIRES_PREFIX)) |
| parseRequires(prefix + REQUIRES_PREFIX, unitRequires); |
| else if (token.startsWith(META_REQUIREMENTS_PREFIX)) |
| parseRequires(prefix + META_REQUIREMENTS_PREFIX, unitMetaRequirements); |
| else if (token.startsWith(INSTRUCTIONS_PREFIX)) |
| parseInstructions(prefix + INSTRUCTIONS_PREFIX, unitInstructions); |
| else { |
| // we ignore elements we do not understand |
| next(); |
| } |
| } |
| |
| InstallableUnitDescription description = unitHostRequirements.isEmpty() ? new InstallableUnitDescription() |
| : new InstallableUnitFragmentDescription(); |
| description.setId(unitId); |
| description.setVersion(unitVersion); |
| description.setSingleton(unitSingleton); |
| description.setFilter(unitFilter); |
| if (unitCopyright != null || unitCopyrightLocation != null) { |
| try { |
| URI uri = unitCopyrightLocation != null ? new URI(unitCopyrightLocation) : null; |
| description.setCopyright(MetadataFactory.createCopyright(uri, unitCopyright)); |
| } catch (URISyntaxException e) { |
| throw new IllegalStateException("bad copyright URI at token: " + current + ", " + currentValue()); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| if (unitTouchpointId != null) |
| description |
| .setTouchpointType(MetadataFactory.createTouchpointType(unitTouchpointId, unitTouchpointVersion)); |
| |
| if (unitUpdateId != null) |
| description.setUpdateDescriptor(MetadataFactory.createUpdateDescriptor(unitUpdateId, unitUpdateRange, |
| unitUpdateSeverity, unitUpdateDescription)); |
| |
| if (!unitLicenses.isEmpty()) |
| description.setLicenses(unitLicenses.toArray(new ILicense[unitLicenses.size()])); |
| |
| if (!unitArtifacts.isEmpty()) |
| description.setArtifacts(unitArtifacts.toArray(new IArtifactKey[unitArtifacts.size()])); |
| |
| if (!unitHostRequirements.isEmpty()) |
| ((InstallableUnitFragmentDescription) description) |
| .setHost(unitHostRequirements.toArray(new IRequirement[unitHostRequirements.size()])); |
| |
| if (!unitProperties.isEmpty()) { |
| for (Entry<String, String> entry : unitProperties.entrySet()) { |
| description.setProperty(entry.getKey(), entry.getValue()); |
| } |
| } |
| |
| if (!unitProvides.isEmpty()) |
| description.setCapabilities(unitProvides.toArray(new IProvidedCapability[unitProvides.size()])); |
| |
| if (!unitRequires.isEmpty()) |
| description.setRequirements(unitRequires.toArray(new IRequirement[unitRequires.size()])); |
| |
| if (!unitMetaRequirements.isEmpty()) |
| description |
| .setMetaRequirements(unitMetaRequirements.toArray(new IRequirement[unitMetaRequirements.size()])); |
| |
| if (!unitInstructions.isEmpty()) |
| description.addTouchpointData(MetadataFactory.createTouchpointData(unitInstructions)); |
| |
| adviceOtherIUs.add(description); |
| } |
| |
| private void parseLicenses(String prefix, List<ILicense> licenses) { |
| while (current != null && current.startsWith(prefix)) { |
| int dotIndex = current.indexOf('.', prefix.length()); |
| if (dotIndex != -1) |
| throw new IllegalStateException("bad token: " + current + " = " + currentValue()); //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| parseLicense(current, licenses); |
| } |
| } |
| |
| private void parseLicense(String prefix, List<ILicense> licenses) { |
| String body = currentValue(); |
| next(); |
| |
| prefix += '.'; |
| String location = null; |
| if (current != null && current.startsWith(prefix)) { |
| if (current.substring(prefix.length()).equals(LOCATION)) { |
| location = currentValue(); |
| } else { |
| // we ignore elements we do not understand |
| } |
| next(); |
| } |
| |
| try { |
| URI uri = location != null ? new URI(location) : null; |
| ILicense license = MetadataFactory.createLicense(uri, body); |
| licenses.add(license); |
| } catch (URISyntaxException e) { |
| throw new IllegalStateException("bad license URI at token: " + current + ", " + currentValue()); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| |
| private void parseArtifacts(String prefix, List<IArtifactKey> artifacts) { |
| while (current != null && current.startsWith(prefix)) { |
| int dotIndex = current.indexOf('.', prefix.length()); |
| if (dotIndex == -1) |
| throw new IllegalStateException("bad token: " + current + " = " + currentValue()); //$NON-NLS-1$ //$NON-NLS-2$ |
| |
| parseArtifact(current.substring(0, dotIndex + 1), artifacts); |
| } |
| } |
| |
| private void parseArtifact(String prefix, List<IArtifactKey> artifacts) { |
| String artifactClassifier = null; |
| String artifactId = null; |
| Version artifactVersion = null; |
| while (current != null && current.startsWith(prefix)) { |
| String token = current.substring(prefix.length()); |
| switch (token) { |
| case CLASSIFIER: |
| artifactClassifier = currentValue(); |
| break; |
| case ID: |
| artifactId = currentValue(); |
| break; |
| case VERSION: |
| artifactVersion = Version.parseVersion(substituteVersionAndQualifier(currentValue())); |
| break; |
| // we ignore elements we do not understand |
| default: |
| break; |
| } |
| |
| next(); |
| } |
| IArtifactKey artifactKey = new ArtifactKey(artifactClassifier, artifactId, artifactVersion); |
| artifacts.add(artifactKey); |
| } |
| |
| private String substituteVersionAndQualifier(String version) { |
| if (version.contains(VERSION_SUBSTITUTION)) { |
| version = replace(version, VERSION_SUBSTITUTION, hostVersion.toString()); |
| } |
| |
| if (version.contains(QUALIFIER_SUBSTITUTION)) { |
| try { |
| String qualifier = PublisherHelper.toOSGiVersion(hostVersion).getQualifier(); |
| if (qualifier == null) |
| qualifier = ""; //$NON-NLS-1$ |
| if (qualifier.length() == 0) { |
| // Note: this works only for OSGi versions and version ranges |
| // where the qualifier if present must be at the end of a version string |
| version = replace(version, "." + QUALIFIER_SUBSTITUTION, ""); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| version = replace(version, QUALIFIER_SUBSTITUTION, qualifier); |
| } catch (UnsupportedOperationException e) { |
| // Version cannot be converted to OSGi |
| } |
| } |
| return version; |
| } |
| |
| // originally from org.eclipse.core.internal.net.StringUtil |
| public static String replace(String source, String from, String to) { |
| if (from.length() == 0) |
| return source; |
| StringBuilder buffer = new StringBuilder(); |
| int current = 0; |
| int pos = 0; |
| while (pos != -1) { |
| pos = source.indexOf(from, current); |
| if (pos == -1) { |
| buffer.append(source.substring(current)); |
| } else { |
| buffer.append(source.substring(current, pos)); |
| buffer.append(to); |
| current = pos + from.length(); |
| } |
| } |
| return buffer.toString(); |
| } |
| |
| public Map<String, String> getProperties() { |
| if (adviceProperties.isEmpty()) |
| return null; |
| return adviceProperties; |
| } |
| |
| public IRequirement[] getRequiredCapabilities() { |
| if (adviceRequires.isEmpty()) |
| return null; |
| |
| return adviceRequires.toArray(new IRequirement[adviceRequires.size()]); |
| } |
| |
| public IProvidedCapability[] getProvidedCapabilities() { |
| if (adviceProvides.isEmpty()) |
| return null; |
| |
| return adviceProvides.toArray(new IProvidedCapability[adviceProvides.size()]); |
| } |
| |
| public IUpdateDescriptor getUpdateDescriptor() { |
| return adviceUpdateDescriptor; |
| } |
| |
| public Map<String, ITouchpointInstruction> getTouchpointInstructions() { |
| if (adviceInstructions.isEmpty()) |
| return null; |
| |
| return adviceInstructions; |
| } |
| |
| public InstallableUnitDescription[] getAdditionalInstallableUnitDescriptions() { |
| if (adviceOtherIUs.isEmpty()) |
| return null; |
| |
| return adviceOtherIUs.toArray(new InstallableUnitDescription[adviceOtherIUs.size()]); |
| } |
| |
| public IRequirement[] getMetaRequiredCapabilities() { |
| if (adviceMetaRequires.isEmpty()) |
| return null; |
| |
| return adviceMetaRequires.toArray(new IRequirement[adviceMetaRequires.size()]); |
| } |
| } |