Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Hallgren2010-10-13 12:49:40 +0000
committerThomas Hallgren2010-10-13 12:49:40 +0000
commitfc38224bb5ba017e14d82c68c63d367d861cf0c0 (patch)
treef78282190fa9a0248c3f09e7849831b3997b374e /bundles/org.eclipse.equinox.p2.metadata
parentec2fb2077073427f4062c97f4d38657d2731c792 (diff)
downloadrt.equinox.p2-fc38224bb5ba017e14d82c68c63d367d861cf0c0.tar.gz
rt.equinox.p2-fc38224bb5ba017e14d82c68c63d367d861cf0c0.tar.xz
rt.equinox.p2-fc38224bb5ba017e14d82c68c63d367d861cf0c0.zip
325126 : omni version needs enum rule to support PHP version scheme
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.metadata')
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/EnumDefinition.java290
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/Messages.java6
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/VersionFormat.java4
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/VersionFormatParser.java224
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/VersionParser.java51
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/VersionVector.java9
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/messages.properties3
7 files changed, 563 insertions, 24 deletions
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/EnumDefinition.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/EnumDefinition.java
new file mode 100644
index 000000000..1d265328f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/EnumDefinition.java
@@ -0,0 +1,290 @@
+package org.eclipse.equinox.internal.p2.metadata;
+
+import java.io.Serializable;
+import java.util.*;
+
+class EnumDefinition implements Comparable<EnumDefinition>, Serializable {
+ static class EnumSegment implements Comparable<EnumSegment>, Serializable {
+ private static final long serialVersionUID = 4737907767214436543L;
+
+ private final int ordinal;
+ private final EnumDefinition definition;
+
+ EnumSegment(int ordinal, EnumDefinition definition) {
+ this.ordinal = ordinal;
+ this.definition = definition;
+ }
+
+ public int compareTo(EnumSegment other) {
+ if (other == this)
+ return 0;
+ if (definition == other.definition)
+ // Same definition. Just compare ordinals
+ return ordinal - other.ordinal;
+
+ String thisId = definition.getIdentifier(ordinal);
+ String otherId = other.definition.getIdentifier(other.ordinal);
+ if (thisId.equals(otherId))
+ return 0;
+
+ int thisOrdinalInOther = other.definition.getOrdinal(thisId);
+ int otherOrdinalInThis = definition.getOrdinal(otherId);
+ if (thisOrdinalInOther >= 0) {
+ if (otherOrdinalInThis >= 0) {
+ // Both identifiers exists in both enums. Let's see if both
+ // enums order them the same way
+ int thisOrder = ordinal - otherOrdinalInThis;
+ int otherOrder = thisOrdinalInOther - other.ordinal;
+ if (thisOrder > 0 && otherOrder > 0)
+ return 1;
+ if (thisOrder < 0 && otherOrder < 0)
+ return -1;
+ // Difference in opinion...
+ } else {
+ // Use the order in other since it has both identifiers and
+ // this enum does not
+ return thisOrdinalInOther - other.ordinal;
+ }
+ } else if (otherOrdinalInThis >= 0) {
+ // Use the order in this since it has both identifiers and the
+ // other does not.
+ return ordinal - otherOrdinalInThis;
+ }
+
+ // We can't compare the enums since neither enum contain both identifiers
+ // or both do, but use different order. Fall back to comparing the definitions
+ return definition.compareTo(other.definition);
+ }
+
+ public boolean equals(Object other) {
+ return other == this || other instanceof EnumSegment && compareTo((EnumSegment) other) == 0;
+ }
+
+ public int hashCode() {
+ return (1 + ordinal) * 31 + definition.getIdentifier(ordinal).hashCode();
+ }
+
+ int getOrdinal() {
+ return ordinal;
+ }
+
+ String getIdentifier() {
+ return definition.getIdentifier(ordinal);
+ }
+
+ void toString(StringBuffer sb) {
+ definition.toString(sb, ordinal);
+ }
+
+ // For ligthweight deserialization
+ private Object readResolve() {
+ return definition.getSegment(ordinal);
+ }
+ }
+
+ private static final long serialVersionUID = 7237775466362654473L;
+ private static final Map<EnumDefinition, EnumSegment[]> enumDefinitionCache = new HashMap<EnumDefinition, EnumSegment[]>();
+
+ private static EnumSegment[] getEnumSegments(EnumDefinition ed) {
+ EnumSegment[] values = enumDefinitionCache.get(ed);
+ if (values == null) {
+ int ordinal = ed.identifiers.length;
+ values = new EnumSegment[ordinal];
+ while (--ordinal >= 0)
+ values[ordinal] = new EnumSegment(ordinal, ed);
+ enumDefinitionCache.put(ed, values);
+ }
+ return values;
+ }
+
+ static EnumDefinition getEnumDefinition(List<List<String>> identifiers) {
+ nextEd: for (EnumDefinition ed : enumDefinitionCache.keySet()) {
+ String[][] defs = ed.identifiers;
+ int ordinal = defs.length;
+ if (ordinal != identifiers.size())
+ continue;
+
+ while (--ordinal >= 0) {
+ String[] def = defs[ordinal];
+ List<String> ldef = identifiers.get(ordinal);
+ int idx = def.length;
+ if (ldef.size() != idx)
+ continue nextEd;
+ while (--idx >= 0)
+ if (!def[idx].equals(ldef.get(idx)))
+ continue nextEd;
+ }
+ return ed;
+ }
+ EnumDefinition ed = new EnumDefinition(identifiers);
+ getEnumSegments(ed);
+ return ed;
+ }
+
+ private final String[][] identifiers;
+ private final int longestLength;
+ private final int shortestLength;
+
+ private EnumDefinition(List<List<String>> identifiers) {
+ int ordinal = identifiers.size();
+ String[][] defs = new String[ordinal][];
+ int minLen = Integer.MAX_VALUE;
+ int maxLen = 0;
+ while (--ordinal >= 0) {
+ List<String> idents = identifiers.get(ordinal);
+ int idx = idents.size();
+ String[] def = idents.toArray(new String[idx]);
+ defs[ordinal] = def;
+ while (--idx >= 0) {
+ int idLen = def[idx].length();
+ if (idLen < minLen)
+ minLen = idLen;
+ if (idLen > maxLen)
+ maxLen = idLen;
+ }
+ }
+ this.shortestLength = minLen;
+ this.longestLength = maxLen;
+ this.identifiers = defs;
+ }
+
+ static EnumSegment getSegment(List<List<String>> identifiers, int ordinal) {
+ return new EnumDefinition(identifiers).getSegment(ordinal);
+ }
+
+ EnumSegment getSegment(int ordinal) {
+ return getEnumSegments(this)[ordinal];
+ }
+
+ /**
+ * Returns the ordinal for the given identifier
+ * @param identifier The identifier
+ * @return The ordinal of the identifier or -1 if it didn't exist.
+ */
+ int getOrdinal(String identifier) {
+ if (identifier != null) {
+ int ordinal = identifiers.length;
+ while (--ordinal >= 0) {
+ String[] idents = identifiers[ordinal];
+ int idx = idents.length;
+ while (--idx >= 0)
+ if (idents[idx].equals(identifier))
+ return ordinal;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the canonical identifier for the given ordinal.
+ * @param ordinal The ordinal number of the desired identifier
+ * @return The identifier or <code>null</code> if the ordinal is out of bounds
+ */
+ String getIdentifier(int ordinal) {
+ return ordinal >= 0 && ordinal < identifiers.length ? identifiers[ordinal][0] : null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ int ordinal = identifiers.length;
+ while (--ordinal > 0) {
+ String[] idents = identifiers[ordinal];
+ int idx = idents.length;
+ while (--idx >= 0)
+ result = 31 * result + idents[idx].hashCode();
+ }
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+ if (!(o instanceof EnumDefinition))
+ return false;
+ String[][] otherIds = ((EnumDefinition) o).identifiers;
+ int ordinal = identifiers.length;
+ if (ordinal != otherIds.length)
+ return false;
+ while (--ordinal >= 0)
+ if (!Arrays.equals(identifiers[ordinal], otherIds[ordinal]))
+ return false;
+ return true;
+ }
+
+ public int compareTo(EnumDefinition o) {
+ if (o == this)
+ return 0;
+
+ int top = identifiers.length;
+ int cmp = top - o.identifiers.length;
+ if (cmp != 0)
+ return cmp;
+
+ for (int idx = 0; idx < top; ++idx) {
+ cmp = identifiers[idx][0].compareTo(o.identifiers[idx][0]);
+ if (cmp != 0)
+ return cmp;
+ }
+ // this should never happen since we use a lightweight pattern
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer bld = new StringBuffer();
+ toString(bld);
+ return bld.toString();
+ }
+
+ public void toString(StringBuffer bld) {
+ bld.append('{');
+ int top = identifiers.length;
+ for (int ordinal = 0;;) {
+ String[] idents = identifiers[ordinal];
+ int identsTop = idents.length;
+ bld.append(idents[0]);
+ for (int idx = 1; idx < identsTop; ++idx) {
+ bld.append('=');
+ bld.append(idents[idx]);
+ }
+ if (++ordinal == top)
+ break;
+ bld.append(',');
+ }
+ bld.append('}');
+ }
+
+ void toString(StringBuffer bld, int selectedOrdinal) {
+ bld.append('{');
+ int top = identifiers.length;
+ for (int ordinal = 0;;) {
+ if (ordinal == selectedOrdinal)
+ bld.append('^');
+ bld.append(identifiers[ordinal][0]);
+ if (++ordinal == top)
+ break;
+ bld.append(',');
+ }
+ bld.append('}');
+ }
+
+ /**
+ * Returns the length of the longest identifier. This method is
+ * used by the parser
+ * @return The length of the longest identifier
+ */
+ int getLongestLength() {
+ return longestLength;
+ }
+
+ /**
+ * Returns the length of the shortest identifier. This method is
+ * used by the parser
+ * @return The length of the shortest identifier
+ */
+ int getShortestLength() {
+ return shortestLength;
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/Messages.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/Messages.java
index 654d4c0aa..eebdf5f49 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/Messages.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/Messages.java
@@ -23,8 +23,12 @@ public class Messages extends NLS {
public static String array_can_not_have_character_group;
+ public static String array_can_not_have_enum;
+
public static String auto_can_not_have_pad_value;
+ public static String bad_enum_definition;
+
public static String cannot_combine_ignore_with_other_instruction;
public static String cannot_combine_range_upper_bound_with_pad_value;
@@ -45,6 +49,8 @@ public class Messages extends NLS {
public static String EOS_after_escape;
+ public static String enum_defined_more_then_once;
+
public static String expected_orignal_after_colon_0;
public static String expected_orignal_after_slash_0;
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/VersionFormat.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/VersionFormat.java
index 98bee1a3d..daf056b64 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/VersionFormat.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/VersionFormat.java
@@ -193,7 +193,9 @@ public class VersionFormat implements IVersionFormat, Serializable {
sb.append('<');
((VersionVector) e).toString(sb, forRange);
sb.append('>');
- } else
+ } else if (e instanceof EnumDefinition.EnumSegment)
+ ((EnumDefinition.EnumSegment) e).toString(sb);
+ else
sb.append(e);
}
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/VersionFormatParser.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/VersionFormatParser.java
index 83170c9a7..2bef09a81 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/VersionFormatParser.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/VersionFormatParser.java
@@ -10,12 +10,11 @@
*******************************************************************************/
package org.eclipse.equinox.internal.p2.metadata;
-import org.eclipse.equinox.p2.metadata.VersionFormatException;
-
import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
+import org.eclipse.equinox.internal.p2.metadata.EnumDefinition.EnumSegment;
import org.eclipse.equinox.internal.p2.metadata.VersionFormat.TreeInfo;
+import org.eclipse.equinox.p2.metadata.VersionFormatException;
import org.eclipse.osgi.util.NLS;
/**
@@ -29,6 +28,69 @@ import org.eclipse.osgi.util.NLS;
*/
class VersionFormatParser {
+ private static class EnumInstruction {
+ private final EnumDefinition definition;
+ private final boolean caseSensitive;
+ private final boolean optional;
+ private final boolean begins;
+
+ EnumInstruction(EnumDefinition definition, boolean caseSensitive, boolean optional, boolean begins) {
+ this.definition = definition;
+ this.caseSensitive = caseSensitive;
+ this.optional = optional;
+ this.begins = begins;
+ }
+
+ EnumSegment getEnumSegment(RangeFragment fragment, String version, int[] posHolder, int maxPos) {
+ int pos = posHolder[0];
+ int len = maxPos - pos;
+ int minLen = definition.getShortestLength();
+ if (minLen > len)
+ return null;
+
+ int maxLen = definition.getLongestLength();
+ if (maxLen < len)
+ len = maxLen;
+
+ ++len;
+ while (--len >= minLen) {
+ int last = pos + len;
+ if (!begins && last < maxPos) {
+ char c = version.charAt(last);
+ if (VersionParser.isLetter(c) && fragment.isAllowed(c)) {
+ // We are not allowed to truncate at this point
+ continue;
+ }
+ }
+ String identifier = version.substring(pos, last);
+ if (!caseSensitive)
+ identifier = identifier.toLowerCase();
+ int ordinal = definition.getOrdinal(identifier);
+ if (ordinal >= 0) {
+ posHolder[0] = pos + len;
+ return definition.getSegment(ordinal);
+ }
+ }
+ return null;
+ }
+
+ void toString(StringBuffer bld) {
+ bld.append('=');
+ definition.toString(bld);
+ if (begins)
+ bld.append('b');
+ if (!caseSensitive)
+ bld.append('i');
+ if (optional)
+ bld.append('?');
+ bld.append(';');
+ }
+
+ public boolean isOptional() {
+ return optional;
+ }
+ }
+
static class Instructions {
char[] characters = null;
Comparable<?> defaultValue = null;
@@ -39,6 +101,7 @@ class VersionFormatParser {
Comparable<?> padValue = null;
int rangeMax = Integer.MAX_VALUE;
int rangeMin = 0;
+ EnumInstruction enumInstruction = null;
}
static final Qualifier EXACT_ONE_QUALIFIER = new Qualifier(1, 1);
@@ -283,7 +346,7 @@ class VersionFormatParser {
return false;
char c = version.charAt(pos);
- if (VersionParser.isDigit(c) && isAllowed(c)) {
+ if (VersionParser.isDigit(c) && isAllowed(c) && (enumInstruction == null || enumInstruction.isOptional())) {
// Parse to next non-digit
//
int start = pos;
@@ -305,13 +368,30 @@ class VersionFormatParser {
return true;
}
+ int start = pos;
+ if (enumInstruction != null) {
+ int[] posHolder = new int[] {pos};
+ EnumSegment es = enumInstruction.getEnumSegment(this, version, posHolder, maxPos);
+ if (es != null) {
+ pos = posHolder[0];
+ int len = pos - start;
+ if (rangeMin > len || len > rangeMax)
+ return false;
+ if (!isIgnored())
+ segments.add(es);
+ info.setPosition(pos);
+ return true;
+ }
+ if (!enumInstruction.isOptional())
+ return false;
+ }
+
if (!(VersionParser.isLetter(c) && isAllowed(c)))
return false;
// Parse to next non-letter or next delimiter
//
- int start = pos++;
- for (; pos < maxPos; ++pos) {
+ for (++pos; pos < maxPos; ++pos) {
c = version.charAt(pos);
if (!(VersionParser.isLetter(c) && isAllowed(c)))
break;
@@ -831,6 +911,7 @@ class VersionFormatParser {
final boolean inverted;
final int rangeMax;
final int rangeMin;
+ final EnumInstruction enumInstruction;
RangeFragment(VersionFormatParser.Instructions instr, Qualifier qualifier) {
super(instr, qualifier);
@@ -839,11 +920,13 @@ class VersionFormatParser {
inverted = false;
rangeMin = 0;
rangeMax = Integer.MAX_VALUE;
+ enumInstruction = null;
} else {
characters = instr.characters;
inverted = instr.inverted;
rangeMin = instr.rangeMin;
rangeMax = instr.rangeMax;
+ enumInstruction = instr.enumInstruction;
}
}
@@ -903,6 +986,8 @@ class VersionFormatParser {
sb.append('}');
sb.append(';');
}
+ if (enumInstruction != null)
+ enumInstruction.toString(sb);
super.toString(sb);
}
}
@@ -986,9 +1071,26 @@ class VersionFormatParser {
if (maxPos < 0)
return false;
+ int start = pos;
+ if (enumInstruction != null) {
+ int[] posHolder = new int[] {pos};
+ EnumSegment es = enumInstruction.getEnumSegment(this, version, posHolder, maxPos);
+ if (es != null) {
+ pos = posHolder[0];
+ int len = pos - start;
+ if (rangeMin > len || len > rangeMax)
+ return false;
+ if (!isIgnored())
+ segments.add(es);
+ info.setPosition(pos);
+ return true;
+ }
+ if (!enumInstruction.isOptional())
+ return false;
+ }
+
// Parse to next delimiter or end of string
//
- int start = pos;
if (characters != null) {
if (anyChar) {
// Swallow everything that matches the allowed characters
@@ -1210,6 +1312,78 @@ class VersionFormatParser {
currentList.add(createDelimiterFragment(ep, parseQualifier()));
}
+ private void parseEnum(Instructions processing) throws VersionFormatException {
+ ++current;
+ ArrayList<List<String>> identifiers = new ArrayList<List<String>>();
+ ArrayList<String> idents = new ArrayList<String>();
+ StringBuffer sb = new StringBuffer();
+ for (;;) {
+ if (current >= eos)
+ throw formatException(Messages.bad_enum_definition);
+
+ char c = format.charAt(current++);
+ while (c != '}' && c != ',' && c != '=') {
+ if (current >= eos || c <= ' ')
+ throw formatException(Messages.bad_enum_definition);
+ if (c == '\\') {
+ c = format.charAt(current++);
+ if (current >= eos)
+ throw formatException(Messages.bad_enum_definition);
+ }
+ sb.append(c);
+ c = format.charAt(current++);
+ }
+ idents.add(sb.toString());
+ sb.setLength(0);
+ if (c == '=')
+ continue;
+
+ identifiers.add(idents);
+ if (c == '}')
+ break;
+
+ // c must be ',' at this point
+ idents = new ArrayList<String>();
+ }
+
+ boolean enumCaseSensitive = true;
+ boolean enumOptional = false;
+ boolean enumBegins = false;
+ while (current < eos) {
+ char c = format.charAt(current);
+ if (c == 'i') {
+ enumCaseSensitive = false;
+ current++;
+ } else if (c == 'b') {
+ enumBegins = true;
+ current++;
+ } else if (c == '?') {
+ enumOptional = true;
+ current++;
+ } else
+ break;
+ }
+
+ // Ensure that all identifiers are unique and make them
+ // lower case if necessary
+ HashSet<String> unique = new HashSet<String>();
+ int ordinal = identifiers.size();
+ while (--ordinal >= 0) {
+ List<String> ids = identifiers.get(ordinal);
+ int idx = ids.size();
+ while (--idx >= 0) {
+ String id = ids.get(idx);
+ if (!enumCaseSensitive)
+ id = id.toLowerCase();
+ if (!unique.add(id))
+ throw formatException(Messages.bad_enum_definition);
+ ids.set(idx, id);
+ }
+ }
+ EnumDefinition enumDefinition = EnumDefinition.getEnumDefinition(identifiers);
+ processing.enumInstruction = new EnumInstruction(enumDefinition, enumCaseSensitive, enumOptional, enumBegins);
+ }
+
private void parseFragment() throws VersionFormatException {
if (current == eos)
throw formatException(Messages.premature_end_of_format);
@@ -1268,9 +1442,10 @@ class VersionFormatParser {
if (ep != null) {
if (ep.characters != null)
throw formatException(Messages.array_can_not_have_character_group);
- if (ep.rangeMax != Integer.MAX_VALUE && ep.padValue != null) {
+ if (ep.rangeMax != Integer.MAX_VALUE && ep.padValue != null)
throw formatException(Messages.cannot_combine_range_upper_bound_with_pad_value);
- }
+ if (ep.enumInstruction != null)
+ throw formatException(Messages.array_can_not_have_enum);
}
if (currentList.isEmpty())
@@ -1416,15 +1591,26 @@ class VersionFormatParser {
throw formatException(Messages.cannot_combine_ignore_with_other_instruction);
parseCharacterGroup(processing);
} else if (c == '{') {
- // ={min,max};
- //
- if (processing.rangeMin != 0 || processing.rangeMax != Integer.MAX_VALUE)
- throw formatException(Messages.range_defined_more_then_once);
- if (processing.ignore)
- throw formatException(Messages.cannot_combine_ignore_with_other_instruction);
- int[] minMax = parseMinMax();
- processing.rangeMin = minMax[0];
- processing.rangeMax = minMax[1];
+ if (current + 1 == eos)
+ throw formatException(Messages.premature_end_of_format);
+
+ if (VersionParser.isDigit(format.charAt(current + 1))) {
+ // ={min,max};
+ //
+ if (processing.rangeMin != 0 || processing.rangeMax != Integer.MAX_VALUE)
+ throw formatException(Messages.range_defined_more_then_once);
+ if (processing.ignore)
+ throw formatException(Messages.cannot_combine_ignore_with_other_instruction);
+ int[] minMax = parseMinMax();
+ processing.rangeMin = minMax[0];
+ processing.rangeMax = minMax[1];
+ } else {
+ // ={enum1,enum2,...};
+ //
+ if (processing.enumInstruction != null)
+ throw formatException(Messages.enum_defined_more_then_once);
+ parseEnum(processing);
+ }
} else {
// =<raw-element>;
if (processing.defaultValue != null)
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/VersionParser.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/VersionParser.java
index 49cb0311d..77eeabc8b 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/VersionParser.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/VersionParser.java
@@ -10,8 +10,7 @@
*******************************************************************************/
package org.eclipse.equinox.internal.p2.metadata;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.*;
import org.eclipse.equinox.p2.metadata.Version;
import org.eclipse.equinox.p2.metadata.VersionFormatException;
import org.eclipse.osgi.util.NLS;
@@ -265,6 +264,17 @@ public abstract class VersionParser {
v = sb.length() == 0 ? VersionVector.MINS_VALUE : sb.toString();
break;
}
+ case '{' : {
+ if (++current == maxPos)
+ return null;
+
+ position[0] = current;
+ v = parseRawEnum(value, position, maxPos);
+ if (v == null)
+ return null;
+ current = position[0];
+ break;
+ }
case '<' : {
if (++current == maxPos)
return null;
@@ -366,6 +376,43 @@ public abstract class VersionParser {
return new VersionVector(rawList.toArray(new Comparable[rawList.size()]), pad);
}
+ private static Comparable<?> parseRawEnum(String value, int[] position, int maxPos) {
+ int pos = position[0];
+ ArrayList<List<String>> identifiers = new ArrayList<List<String>>();
+ int ordinal = -1;
+ StringBuffer sb = new StringBuffer();
+ for (;;) {
+ if (pos >= maxPos)
+ return null;
+
+ char c = value.charAt(pos++);
+ while (c != '}' && c != ',') {
+ if (pos == maxPos)
+ return null;
+ if (c <= ' ')
+ return null;
+ if (c == '\\' || c == '^') {
+ if (c == '^')
+ ordinal = identifiers.size();
+ c = value.charAt(pos++);
+ if (pos == maxPos)
+ return null;
+ }
+ sb.append(c);
+ c = value.charAt(pos++);
+ }
+ identifiers.add(Collections.singletonList(sb.toString()));
+ if (c == '}')
+ break;
+ // c must be ',' at this point
+ sb.setLength(0);
+ }
+ if (ordinal == -1)
+ return null;
+ position[0] = pos;
+ return EnumDefinition.getSegment(identifiers, ordinal);
+ }
+
public static int skipWhite(String string, int pos) {
int top = string.length();
while (pos < top && string.charAt(pos) <= ' ')
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/VersionVector.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/VersionVector.java
index 1d1e312d3..acf47a96f 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/VersionVector.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/internal/p2/metadata/VersionVector.java
@@ -32,7 +32,7 @@ public class VersionVector implements Comparable<VersionVector>, Serializable {
}
public int compareTo(Object o) {
- return o == this ? 0 : (o == MAX_VALUE || o instanceof Integer || o instanceof VersionVector ? -1 : 1);
+ return o == this ? 0 : (o == MAX_VALUE || o instanceof Integer || o instanceof EnumDefinition.EnumSegment || o instanceof VersionVector ? -1 : 1);
}
// For singleton deserialization
@@ -222,12 +222,17 @@ public class VersionVector implements Comparable<VersionVector>, Serializable {
return 1;
if (b instanceof Integer)
return -1;
+
if (a instanceof VersionVector)
return (b instanceof VersionVector) ? ((VersionVector) a).compareTo((VersionVector) b) : 1;
-
if (b instanceof VersionVector)
return -1;
+ if (a instanceof EnumDefinition.EnumSegment)
+ return (b instanceof EnumDefinition.EnumSegment) ? ((EnumDefinition.EnumSegment) a).compareTo((EnumDefinition.EnumSegment) b) : 1;
+ if (b instanceof EnumDefinition.EnumSegment)
+ return -1;
+
throw new IllegalArgumentException();
}
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 540b61526..58b8904b0 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
@@ -11,7 +11,9 @@
_0_is_not_a_valid_qualifier_in_osgi_1=The {0} value is invalid in OSGi version: "{1}"
array_can_not_be_empty=Array format can not be empty
array_can_not_have_character_group=Array format can not have a character group
+array_can_not_have_enum=Array format can not have an enum specifier
auto_can_not_have_pad_value=Auto format can not have a pad value
+bad_enum_definition=Bad definition of enumerator
cannot_combine_ignore_with_other_instruction=Cannot combine ignore with other instruction
cannot_combine_range_upper_bound_with_pad_value=Cannot combine range upper bound with pad value
character_group_defined_more_then_once=Character group was defined more then once
@@ -22,6 +24,7 @@ delimiter_can_not_have_default_value=A delimiter cannot have a default value
delimiter_can_not_have_pad_value=A delimiter cannot have a pad value
delimiter_can_not_have_range=A delimiter cannot have a range
EOS_after_escape=End of string was encountere after the escape character
+enum_defined_more_then_once=Enumeration was defined more then once
expected_orignal_after_colon_0=An original version was expected after colon: {0}
expected_orignal_after_slash_0=A format or colon was expected after slash: {0}
expected_slash_after_raw_vector_0=A slash was expected after a raw version: {0}

Back to the top