| /******************************************************************************* |
| * Copyright (c) 2000, 2015 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 |
| * Sergey Prigogin (Google) - use parameterized types (bug 442021) |
| *******************************************************************************/ |
| package org.eclipse.core.runtime; |
| |
| import java.util.StringTokenizer; |
| import java.util.Vector; |
| import org.eclipse.core.internal.runtime.CommonMessages; |
| import org.eclipse.core.internal.runtime.IRuntimeConstants; |
| import org.eclipse.osgi.util.NLS; |
| import org.osgi.framework.Version; |
| |
| /** |
| * <p> |
| * Version identifier for a plug-in. In its string representation, |
| * it consists of up to 4 tokens separated by a decimal point. |
| * The first 3 tokens are positive integer numbers, the last token |
| * is an uninterpreted string (no whitespace characters allowed). |
| * For example, the following are valid version identifiers |
| * (as strings): |
| * <ul> |
| * <li><code>0.0.0</code></li> |
| * <li><code>1.0.127564</code></li> |
| * <li><code>3.7.2.build-127J</code></li> |
| * <li><code>1.9</code> (interpreted as <code>1.9.0</code>)</li> |
| * <li><code>3</code> (interpreted as <code>3.0.0</code>)</li> |
| * </ul> |
| * </p> |
| * <p> |
| * The version identifier can be decomposed into a major, minor, |
| * service level component and qualifier components. A difference |
| * in the major component is interpreted as an incompatible version |
| * change. A difference in the minor (and not the major) component |
| * is interpreted as a compatible version change. The service |
| * level component is interpreted as a cumulative and compatible |
| * service update of the minor version component. The qualifier is |
| * not interpreted, other than in version comparisons. The |
| * qualifiers are compared using lexicographical string comparison. |
| * </p> |
| * <p> |
| * Version identifiers can be matched as perfectly equal, equivalent, |
| * compatible or greaterOrEqual. |
| * </p><p> |
| * This class can be used without OSGi running. |
| * </p><p> |
| * Clients may instantiate; not intended to be subclassed by clients. |
| * </p> |
| * @see java.lang.String#compareTo(java.lang.String) |
| * @deprecated clients should use {@link org.osgi.framework.Version} instead |
| */ |
| @Deprecated |
| public final class PluginVersionIdentifier { |
| |
| private Version version; |
| |
| private static final String SEPARATOR = "."; //$NON-NLS-1$ |
| |
| /** |
| * Creates a plug-in version identifier from its components. |
| * |
| * @param major major component of the version identifier |
| * @param minor minor component of the version identifier |
| * @param service service update component of the version identifier |
| */ |
| public PluginVersionIdentifier(int major, int minor, int service) { |
| this(major, minor, service, null); |
| } |
| |
| /** |
| * Creates a plug-in version identifier from its components. |
| * |
| * @param major major component of the version identifier |
| * @param minor minor component of the version identifier |
| * @param service service update component of the version identifier |
| * @param qualifier qualifier component of the version identifier. |
| * Qualifier characters that are not a letter or a digit are replaced. |
| */ |
| public PluginVersionIdentifier(int major, int minor, int service, String qualifier) { |
| // Do the test outside of the assert so that they 'Policy.bind' |
| // will not be evaluated each time (including cases when we would |
| // have passed by the assert). |
| |
| if (major < 0) |
| Assert.isTrue(false, NLS.bind(CommonMessages.parse_postiveMajor, major + SEPARATOR + minor + SEPARATOR + service + SEPARATOR + qualifier)); |
| if (minor < 0) |
| Assert.isTrue(false, NLS.bind(CommonMessages.parse_postiveMinor, major + SEPARATOR + minor + SEPARATOR + service + SEPARATOR + qualifier)); |
| if (service < 0) |
| Assert.isTrue(false, NLS.bind(CommonMessages.parse_postiveService, major + SEPARATOR + minor + SEPARATOR + service + SEPARATOR + qualifier)); |
| |
| this.version = new Version(major, minor, service, qualifier); |
| } |
| |
| /** |
| * Creates a plug-in version identifier from the given string. |
| * The string representation consists of up to 4 tokens |
| * separated by decimal point. |
| * For example, the following are valid version identifiers |
| * (as strings): |
| * <ul> |
| * <li><code>0.0.0</code></li> |
| * <li><code>1.0.127564</code></li> |
| * <li><code>3.7.2.build-127J</code></li> |
| * <li><code>1.9</code> (interpreted as <code>1.9.0</code>)</li> |
| * <li><code>3</code> (interpreted as <code>3.0.0</code>)</li> |
| * </ul> |
| * </p> |
| * |
| * @param versionId string representation of the version identifier. |
| * Qualifier characters that are not a letter or a digit are replaced. |
| */ |
| public PluginVersionIdentifier(String versionId) { |
| Object[] parts = parseVersion(versionId); |
| version = new Version(((Integer) parts[0]).intValue(), ((Integer) parts[1]).intValue(), ((Integer) parts[2]).intValue(), (String) parts[3]); |
| } |
| |
| /** |
| * Validates the given string as a plug-in version identifier. |
| * |
| * @param version the string to validate |
| * @return a status object with code <code>IStatus.OK</code> if |
| * the given string is valid as a plug-in version identifier, otherwise a status |
| * object indicating what is wrong with the string |
| * @since 2.0 |
| */ |
| public static IStatus validateVersion(String version) { |
| try { |
| parseVersion(version); |
| } catch (RuntimeException e) { |
| return new Status(IStatus.ERROR, IRuntimeConstants.PI_RUNTIME, IStatus.ERROR, e.getMessage(), e); |
| } |
| return Status.OK_STATUS; |
| } |
| |
| private static Object[] parseVersion(String versionId) { |
| |
| // Do the test outside of the assert so that they 'Policy.bind' |
| // will not be evaluated each time (including cases when we would |
| // have passed by the assert). |
| if (versionId == null) |
| Assert.isNotNull(null, CommonMessages.parse_emptyPluginVersion); |
| String s = versionId.trim(); |
| if (s.equals("")) //$NON-NLS-1$ |
| Assert.isTrue(false, CommonMessages.parse_emptyPluginVersion); |
| if (s.startsWith(SEPARATOR)) |
| Assert.isTrue(false, NLS.bind(CommonMessages.parse_separatorStartVersion, s)); |
| if (s.endsWith(SEPARATOR)) |
| Assert.isTrue(false, NLS.bind(CommonMessages.parse_separatorEndVersion, s)); |
| if (s.indexOf(SEPARATOR + SEPARATOR) != -1) |
| Assert.isTrue(false, NLS.bind(CommonMessages.parse_doubleSeparatorVersion, s)); |
| |
| StringTokenizer st = new StringTokenizer(s, SEPARATOR); |
| Vector<String> elements = new Vector<>(4); |
| |
| while (st.hasMoreTokens()) |
| elements.addElement(st.nextToken()); |
| |
| int elementSize = elements.size(); |
| |
| if (elementSize <= 0) |
| Assert.isTrue(false, NLS.bind(CommonMessages.parse_oneElementPluginVersion, s)); |
| if (elementSize > 4) |
| Assert.isTrue(false, NLS.bind(CommonMessages.parse_fourElementPluginVersion, s)); |
| |
| int[] numbers = new int[3]; |
| try { |
| numbers[0] = Integer.parseInt(elements.elementAt(0)); |
| if (numbers[0] < 0) |
| Assert.isTrue(false, NLS.bind(CommonMessages.parse_postiveMajor, s)); |
| } catch (NumberFormatException nfe) { |
| Assert.isTrue(false, NLS.bind(CommonMessages.parse_numericMajorComponent, s)); |
| } |
| |
| try { |
| if (elementSize >= 2) { |
| numbers[1] = Integer.parseInt(elements.elementAt(1)); |
| if (numbers[1] < 0) |
| Assert.isTrue(false, NLS.bind(CommonMessages.parse_postiveMinor, s)); |
| } else |
| numbers[1] = 0; |
| } catch (NumberFormatException nfe) { |
| Assert.isTrue(false, NLS.bind(CommonMessages.parse_numericMinorComponent, s)); |
| } |
| |
| try { |
| if (elementSize >= 3) { |
| numbers[2] = Integer.parseInt(elements.elementAt(2)); |
| if (numbers[2] < 0) |
| Assert.isTrue(false, NLS.bind(CommonMessages.parse_postiveService, s)); |
| } else |
| numbers[2] = 0; |
| } catch (NumberFormatException nfe) { |
| Assert.isTrue(false, NLS.bind(CommonMessages.parse_numericServiceComponent, s)); |
| } |
| |
| // "result" is a 4-element array with the major, minor, service, and qualifier |
| Object[] result = new Object[4]; |
| result[0] = new Integer(numbers[0]); |
| result[1] = new Integer(numbers[1]); |
| result[2] = new Integer(numbers[2]); |
| if (elementSize >= 4) |
| result[3] = elements.elementAt(3); |
| else |
| result[3] = ""; //$NON-NLS-1$ |
| return result; |
| } |
| |
| /** |
| * Compare version identifiers for equality. Identifiers are |
| * equal if all of their components are equal. |
| * |
| * @param object an object to compare |
| * @return whether or not the two objects are equal |
| */ |
| @Override |
| public boolean equals(Object object) { |
| if (!(object instanceof PluginVersionIdentifier)) |
| return false; |
| PluginVersionIdentifier v = (PluginVersionIdentifier) object; |
| return version.equals(v.version); |
| } |
| |
| /** |
| * Returns a hash code value for the object. |
| * |
| * @return an integer which is a hash code value for this object. |
| */ |
| @Override |
| public int hashCode() { |
| return version.hashCode(); |
| } |
| |
| /** |
| * Returns the major (incompatible) component of this |
| * version identifier. |
| * |
| * @return the major version |
| */ |
| public int getMajorComponent() { |
| return version.getMajor(); |
| } |
| |
| /** |
| * Returns the minor (compatible) component of this |
| * version identifier. |
| * |
| * @return the minor version |
| */ |
| public int getMinorComponent() { |
| return version.getMinor(); |
| } |
| |
| /** |
| * Returns the service level component of this |
| * version identifier. |
| * |
| * @return the service level |
| */ |
| public int getServiceComponent() { |
| return version.getMicro(); |
| } |
| |
| /** |
| * Returns the qualifier component of this |
| * version identifier. |
| * |
| * @return the qualifier |
| */ |
| public String getQualifierComponent() { |
| return version.getQualifier(); |
| } |
| |
| /** |
| * Compares two version identifiers to see if this one is |
| * greater than or equal to the argument. |
| * <p> |
| * A version identifier is considered to be greater than or equal |
| * if its major component is greater than the argument major |
| * component, or the major components are equal and its minor component |
| * is greater than the argument minor component, or the |
| * major and minor components are equal and its service component is |
| * greater than the argument service component, or the major, minor and |
| * service components are equal and the qualifier component is |
| * greater than the argument qualifier component (using lexicographic |
| * string comparison), or all components are equal. |
| * </p> |
| * |
| * @param id the other version identifier |
| * @return <code>true</code> is this version identifier |
| * is compatible with the given version identifier, and |
| * <code>false</code> otherwise |
| * @since 2.0 |
| */ |
| public boolean isGreaterOrEqualTo(PluginVersionIdentifier id) { |
| if (id == null) |
| return false; |
| if (getMajorComponent() > id.getMajorComponent()) |
| return true; |
| if ((getMajorComponent() == id.getMajorComponent()) && (getMinorComponent() > id.getMinorComponent())) |
| return true; |
| if ((getMajorComponent() == id.getMajorComponent()) && (getMinorComponent() == id.getMinorComponent()) && (getServiceComponent() > id.getServiceComponent())) |
| return true; |
| if ((getMajorComponent() == id.getMajorComponent()) && (getMinorComponent() == id.getMinorComponent()) && (getServiceComponent() == id.getServiceComponent()) && (getQualifierComponent().compareTo(id.getQualifierComponent()) >= 0)) |
| return true; |
| return false; |
| } |
| |
| /** |
| * Compares two version identifiers for compatibility. |
| * <p> |
| * A version identifier is considered to be compatible if its major |
| * component equals to the argument major component, and its minor component |
| * is greater than or equal to the argument minor component. |
| * If the minor components are equal, than the service level of the |
| * version identifier must be greater than or equal to the service level |
| * of the argument identifier. If the service levels are equal, the two |
| * version identifiers are considered to be equivalent if this qualifier is |
| * greater or equal to the qualifier of the argument (using lexicographic |
| * string comparison). |
| * </p> |
| * |
| * @param id the other version identifier |
| * @return <code>true</code> is this version identifier |
| * is compatible with the given version identifier, and |
| * <code>false</code> otherwise |
| */ |
| public boolean isCompatibleWith(PluginVersionIdentifier id) { |
| if (id == null) |
| return false; |
| if (getMajorComponent() != id.getMajorComponent()) |
| return false; |
| if (getMinorComponent() > id.getMinorComponent()) |
| return true; |
| if (getMinorComponent() < id.getMinorComponent()) |
| return false; |
| if (getServiceComponent() > id.getServiceComponent()) |
| return true; |
| if (getServiceComponent() < id.getServiceComponent()) |
| return false; |
| if (getQualifierComponent().compareTo(id.getQualifierComponent()) >= 0) |
| return true; |
| return false; |
| } |
| |
| /** |
| * Compares two version identifiers for equivalency. |
| * <p> |
| * Two version identifiers are considered to be equivalent if their major |
| * and minor component equal and are at least at the same service level |
| * as the argument. If the service levels are equal, the two version |
| * identifiers are considered to be equivalent if this qualifier is |
| * greater or equal to the qualifier of the argument (using lexicographic |
| * string comparison). |
| * |
| * </p> |
| * |
| * @param id the other version identifier |
| * @return <code>true</code> is this version identifier |
| * is equivalent to the given version identifier, and |
| * <code>false</code> otherwise |
| */ |
| public boolean isEquivalentTo(PluginVersionIdentifier id) { |
| if (id == null) |
| return false; |
| if (getMajorComponent() != id.getMajorComponent()) |
| return false; |
| if (getMinorComponent() != id.getMinorComponent()) |
| return false; |
| if (getServiceComponent() > id.getServiceComponent()) |
| return true; |
| if (getServiceComponent() < id.getServiceComponent()) |
| return false; |
| if (getQualifierComponent().compareTo(id.getQualifierComponent()) >= 0) |
| return true; |
| return false; |
| } |
| |
| /** |
| * Compares two version identifiers for perfect equality. |
| * <p> |
| * Two version identifiers are considered to be perfectly equal if their |
| * major, minor, service and qualifier components are equal |
| * </p> |
| * |
| * @param id the other version identifier |
| * @return <code>true</code> is this version identifier |
| * is perfectly equal to the given version identifier, and |
| * <code>false</code> otherwise |
| * @since 2.0 |
| */ |
| public boolean isPerfect(PluginVersionIdentifier id) { |
| if (id == null) |
| return false; |
| if ((getMajorComponent() != id.getMajorComponent()) || (getMinorComponent() != id.getMinorComponent()) || (getServiceComponent() != id.getServiceComponent()) || (!getQualifierComponent().equals(id.getQualifierComponent()))) |
| return false; |
| return true; |
| } |
| |
| /** |
| * Compares two version identifiers for order using multi-decimal |
| * comparison. |
| * |
| * @param id the other version identifier |
| * @return <code>true</code> is this version identifier |
| * is greater than the given version identifier, and |
| * <code>false</code> otherwise |
| */ |
| public boolean isGreaterThan(PluginVersionIdentifier id) { |
| |
| if (id == null) { |
| if (getMajorComponent() == 0 && getMinorComponent() == 0 && getServiceComponent() == 0 && getQualifierComponent().equals("")) //$NON-NLS-1$ |
| return false; |
| return true; |
| } |
| |
| if (getMajorComponent() > id.getMajorComponent()) |
| return true; |
| if (getMajorComponent() < id.getMajorComponent()) |
| return false; |
| if (getMinorComponent() > id.getMinorComponent()) |
| return true; |
| if (getMinorComponent() < id.getMinorComponent()) |
| return false; |
| if (getServiceComponent() > id.getServiceComponent()) |
| return true; |
| if (getServiceComponent() < id.getServiceComponent()) |
| return false; |
| if (getQualifierComponent().compareTo(id.getQualifierComponent()) > 0) |
| return true; |
| return false; |
| |
| } |
| |
| /** |
| * Returns the string representation of this version identifier. |
| * The result satisfies |
| * <code>vi.equals(new PluginVersionIdentifier(vi.toString()))</code>. |
| * |
| * @return the string representation of this plug-in version identifier |
| */ |
| @Override |
| public String toString() { |
| return version.toString(); |
| } |
| |
| } |