Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPascal Rapicault2011-11-14 01:21:40 +0000
committerPascal Rapicault2011-11-14 01:22:55 +0000
commitbf5f28e9c3c61f074c9206421d1a802595a87c67 (patch)
tree28623116b0b7e703b6994cde42f476b9ad897725
parent79595ec1c9670b7e748932f0ccdb187412cb9500 (diff)
downloadrt.equinox.p2-bf5f28e9c3c61f074c9206421d1a802595a87c67.tar.gz
rt.equinox.p2-bf5f28e9c3c61f074c9206421d1a802595a87c67.tar.xz
rt.equinox.p2-bf5f28e9c3c61f074c9206421d1a802595a87c67.zip
Add test for lucky button
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/AbstractProvisioningTest.java4
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/IUDescription.java19
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/IULoader.java50
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ReducedCUDFParser.java608
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/LuckyHelper.java87
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/LuckyTest.java51
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/LuckyTest2.java57
7 files changed, 876 insertions, 0 deletions
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/AbstractProvisioningTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/AbstractProvisioningTest.java
index 19fee34da..65a7dcd2f 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/AbstractProvisioningTest.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/AbstractProvisioningTest.java
@@ -1020,6 +1020,10 @@ public abstract class AbstractProvisioningTest extends TestCase {
req.setInstallableUnitInclusionRules(ius[i], strict ? ProfileInclusionRules.createStrictInclusionRule(ius[i]) : ProfileInclusionRules.createOptionalInclusionRule(ius[i]));
}
+ return install(req, planner, engine);
+ }
+
+ protected IStatus install(ProfileChangeRequest req, IPlanner planner, IEngine engine) {
IProvisioningPlan plan = planner.getProvisioningPlan(req, null, null);
if (plan.getStatus().getSeverity() == IStatus.ERROR || plan.getStatus().getSeverity() == IStatus.CANCEL)
return plan.getStatus();
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/IUDescription.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/IUDescription.java
new file mode 100644
index 000000000..6b667f8d3
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/IUDescription.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sonatype, Inc. 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:
+ * Sonatype, Inc. - initial implementation and ideas
+ ******************************************************************************/
+
+package org.eclipse.equinox.p2.tests;
+
+import java.lang.annotation.*;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD, ElementType.LOCAL_VARIABLE})
+public @interface IUDescription {
+ public String content();
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/IULoader.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/IULoader.java
new file mode 100644
index 000000000..ca17737bc
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/IULoader.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Sonatype, Inc. 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:
+ * Sonatype, Inc. - initial implementation and ideas
+ ******************************************************************************/
+package org.eclipse.equinox.p2.tests;
+
+import java.io.*;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+
+public class IULoader {
+
+ private static Annotation[] annos;
+
+ public static void loadIUs(Object o) {
+ Class<? extends Object> classWithIUs = o.getClass();
+ annos = classWithIUs.getAnnotations();
+ for (int i = 0; i < annos.length; i++) {
+ System.out.println(annos[i]);
+ }
+
+ Field[] fields = classWithIUs.getFields();
+ for (int i = 0; i < fields.length; i++) {
+ Annotation[] a = fields[i].getAnnotations();
+ for (int j = 0; j < a.length; j++) {
+ if (a[j] instanceof IUDescription) {
+ IUDescription ml = (IUDescription) a[j]; // here it is !!!
+ ReducedCUDFParser parser = new ReducedCUDFParser();
+ InputStream is = new ByteArrayInputStream(ml.content().getBytes());
+ parser.parse(is, false, null);
+ try {
+ fields[i].set(o, parser.getIU());
+ is.close();
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ReducedCUDFParser.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ReducedCUDFParser.java
new file mode 100644
index 000000000..1f2917fb0
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ReducedCUDFParser.java
@@ -0,0 +1,608 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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 implementation and ideas
+ * Sonatype Inc. - trim down for annotation work
+ ******************************************************************************/
+
+package org.eclipse.equinox.p2.tests;
+
+import java.io.*;
+import java.util.*;
+import org.eclipse.equinox.internal.p2.metadata.*;
+import org.eclipse.equinox.p2.metadata.*;
+import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription;
+
+public class ReducedCUDFParser {
+
+ private static final boolean DEBUG = false; //TO SET TO FALSE FOR COMPETITION
+ private static final boolean TIMING = true; //TO SET TO FALSE FOR COMPETITION
+ private InstallableUnitDescription currentIU = null;
+ // private ProfileChangeRequest currentRequest = null;
+ private List allIUs = new ArrayList();
+ // private QueryableArray query = null;
+ private List currentKeepRequests = new ArrayList();
+
+ class Tuple {
+ String name;
+ String version;
+ String operator;
+ Set extraData;
+
+ Tuple(String line) {
+ String[] tuple = new String[3];
+ int i = 0;
+ for (StringTokenizer iter = new StringTokenizer(line, " \t"); iter.hasMoreTokens(); i++)
+ tuple[i] = iter.nextToken().trim();
+ name = tuple[0];
+ operator = tuple[1];
+ version = tuple[2];
+ }
+ }
+
+ //
+ // public ProfileChangeRequest parse(File file) {
+ // return parse(file, false, null);
+ // }
+ //
+ // public ProfileChangeRequest parse(File file, boolean includeRecommends, String sumProperty) {
+ // try {
+ // return parse(new FileInputStream(file), includeRecommends, sumProperty);
+ // } catch (FileNotFoundException e) {
+ // e.printStackTrace();
+ // return null;
+ // }
+ // }
+ //
+ // public ProfileChangeRequest parse(InputStream stream) {
+ // return parse(stream, false, null);
+ // }
+ //
+ // public ProfileChangeRequest parse(InputStream stream, String sumProperty) {
+ // return parse(stream, false, sumProperty);
+ // }
+
+ public void parse(InputStream stream, boolean includeRecommends, String sumProperty) {
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
+ String next = reader.readLine();
+ while (true) {
+
+ // look-ahead to check for line continuation
+ String line = next;
+ for (next = reader.readLine(); next != null && next.length() > 1 && next.charAt(0) == ' '; next = reader.readLine()) {
+ line = line + next.substring(1);
+ }
+
+ // terminating condition of the loop... reached the end of the file
+ if (line == null) {
+ validateAndAddIU();
+ break;
+ }
+
+ // end of stanza
+ if (line.trim().length() == 0) {
+ validateAndAddIU();
+ continue;
+ }
+
+ // preamble stanza
+ if (line.startsWith("#") || line.startsWith("preamble: ") || line.startsWith("property: ") || line.startsWith("univ-checksum: ")) {
+ // ignore
+ }
+
+ // // request stanza
+ // else if (line.startsWith("request: ")) {
+ // handleRequest(line);
+ // } else if (line.startsWith("install: ")) {
+ // handleInstall(line);
+ // } else if (line.startsWith("upgrade: ")) {
+ // handleUpgrade(line);
+ // } else if (line.startsWith("remove: ")) {
+ // handleRemove(line);
+ // }
+
+ // package stanza
+ else if (line.startsWith("package: ")) {
+ handlePackage(line);
+ } else if (line.startsWith("version: ")) {
+ handleVersion(line);
+ // } else if (line.startsWith("installed: ")) {
+ // handleInstalled(line);
+ } else if (line.startsWith("depends: ")) {
+ handleDepends(line);
+ // } else if (line.startsWith("conflicts: ")) {
+ // handleConflicts(line);
+ } else if (line.startsWith("provides: ")) {
+ handleProvides(line);
+ } else if (line.startsWith("singleton:")) {
+ handleSingleton(line);
+ }
+ // } else if (line.startsWith("expected: ")) {
+ // handleExpected(line);
+ // } else if (line.startsWith("recommends: ") && includeRecommends) {
+ // handleRecommends(line);
+ // } else if (line.startsWith("keep: ")) {
+ // handleKeep(line);
+ // } else if (sumProperty != null && line.startsWith(sumProperty + ":")) {
+ // handleSumProperty(line, sumProperty);
+ // }
+ }
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ if (reader != null)
+ try {
+ reader.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ if (TIMING)
+ // Log.println("Time to parse:" + (System.currentTimeMillis() - start));
+ if (DEBUG)
+ for (Iterator iter = allIUs.iterator(); iter.hasNext();)
+ debug((InstallableUnit) iter.next());
+ // if (FORCE_QUERY) {
+ // if (query == null)
+ // initializeQueryableArray();
+ // if (currentRequest == null)
+ // currentRequest = new ProfileChangeRequest(query);
+ // }
+ // debug(currentRequest);
+ // return currentRequest;
+ }
+
+ // private void handleSumProperty(String line, String sumProperty) {
+ // String value = line.substring(sumProperty.length() + 1).trim();
+ // try {
+ // currentIU.setSumProperty(Long.valueOf(value));
+ // } catch (NumberFormatException ex) {
+ // throw new IllegalArgumentException("The value \"" + value + "\" of property \"" + sumProperty + "\" cannot be summed up");
+ // }
+ // }
+
+ // private void handleKeep(String line) {
+ // line = line.substring("keep: ".length());
+ // if (line.contains("version")) {
+ // currentKeepRequests.add(MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, currentIU.getId(), new VersionRange(currentIU.getVersion(), true, currentIU.getVersion(), true), null, false, false, true));
+ // return;
+ // }
+ // if (line.contains("package")) {
+ // currentKeepRequests.add(new RequiredCapability(currentIU.getId(), VersionRange.emptyRange, false));
+ // return;
+ // }
+ // if (line.contains("none"))
+ // return;
+ // if (line.contains("feature")) {
+ // IProvidedCapability[] caps = currentIU.getProvidedCapabilities();
+ // for (int i = 0; i < caps.length; i++) {
+ // if (!caps[i].getName().equals(currentIU.getId()))
+ // currentKeepRequests.add(new RequiredCapability(caps[i].getName(), caps[i].getVersion(), false));
+ // }
+ // }
+ //
+ // }
+
+ // private void handleExpected(String line) {
+ // currentRequest.setExpected(Integer.decode(line.substring("expected: ".length()).trim()).intValue());
+ // }
+
+ private void handleSingleton(String line) {
+ currentIU.setSingleton(line.contains("true") ? true : false);
+ }
+
+ /*
+ * Ensure that the current IU that we have been building is validate and if so, then
+ * add it to our collected list of all converted IUs from the file.
+ */
+ private void validateAndAddIU() {
+ if (currentIU == null)
+ return;
+ // For a package stanza, the id and version are the only mandatory elements
+ if (currentIU.getId() == null)
+ throw new IllegalStateException("Malformed \'package\' stanza. No package element found.");
+ if (currentIU.getVersion() == null)
+ throw new IllegalStateException("Malformed \'package\' stanza. Package " + currentIU.getId() + " does not have a version.");
+ if (currentIU.getProvidedCapabilities().size() == 0) {
+ currentIU.setCapabilities(new IProvidedCapability[] {MetadataFactory.createProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, currentIU.getId(), currentIU.getVersion()), MetadataFactory.createProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, currentIU.getId(), currentIU.getVersion())});
+ }
+ currentIU.setUpdateDescriptor(MetadataFactory.createUpdateDescriptor(currentIU.getId(), new VersionRange(Version.emptyVersion, true, currentIU.getVersion(), false), IUpdateDescriptor.NORMAL, null));
+ // if (currentIU.isInstalled()) {
+ // keepRequests.addAll(currentKeepRequests);
+ // }
+ allIUs.add(MetadataFactory.createInstallableUnit(currentIU));
+ // reset to be ready for the next stanza
+ currentIU = null;
+ currentKeepRequests.clear();
+ }
+
+ // private void handleInstalled(String line) {
+ // String value = line.substring("installed: ".length());
+ // if (value.length() != 0) {
+ // if (DEBUG)
+ // if (!Boolean.valueOf(value).booleanValue()) {
+ // System.err.println("Unexcepted value for installed.");
+ // return;
+ // }
+ // currentIU.setInstalled(true);
+ // preInstalled.add(new RequiredCapability(currentIU.getId(), new VersionRange(currentIU.getVersion()), true));
+ // }
+ // }
+
+ // private void handleInstall(String line) {
+ // line = line.substring("install: ".length());
+ // List installRequest = createRequires(line, true, false, true);
+ // for (Iterator iterator = installRequest.iterator(); iterator.hasNext();) {
+ // currentRequest.addInstallableUnit((IRequiredCapability) iterator.next());
+ // }
+ // return;
+ // }
+
+ // private void handleRequest(String line) {
+ // initializeQueryableArray();
+ // currentRequest = new ProfileChangeRequest(query);
+ // currentRequest.setPreInstalledIUs(preInstalled);
+ // currentRequest.setContrainstFromKeep(keepRequests);
+ // }
+ //
+ // private void handleRemove(String line) {
+ // line = line.substring("remove: ".length());
+ // List removeRequest = createRequires(line, true, false, true);
+ // for (Iterator iterator = removeRequest.iterator(); iterator.hasNext();) {
+ // currentRequest.removeInstallableUnit((IRequiredCapability) iterator.next());
+ // }
+ // return;
+ // }
+
+ // private void initializeQueryableArray() {
+ // query = new QueryableArray((InstallableUnit[]) allIUs.toArray(new InstallableUnit[allIUs.size()]));
+ // }
+
+ // private void handleUpgrade(String line) {
+ // line = line.substring("upgrade: ".length());
+ // List updateRequest = createRequires(line, true, false, true);
+ // for (Iterator iterator = updateRequest.iterator(); iterator.hasNext();) {
+ // IRequiredCapability requirement = (IRequiredCapability) iterator.next();
+ // currentRequest.upgradeInstallableUnit(requirement);
+ //
+ // //Add a requirement forcing uniqueness of the upgraded package in the resulting solution
+ // currentRequest.upgradeInstallableUnit(new RequiredCapability(requirement.getName(), VersionRange.emptyRange, 1));
+ //
+ // //Add a requirement forcing the solution to be greater or equal to the highest installed version
+ // requirement = getHighestInstalledVersion(requirement);
+ // if (requirement != null)
+ // currentRequest.upgradeInstallableUnit(requirement);
+ // }
+ // return;
+ // }
+ //
+ // private IRequiredCapability getHighestInstalledVersion(IRequiredCapability req) {
+ // Version highestVersion = null;
+ // Collector c = query.query(new CapabilityQuery(req), new Collector(), null);
+ // for (Iterator iterator = c.iterator(); iterator.hasNext();) {
+ // InstallableUnit candidate = (InstallableUnit) iterator.next();
+ // if (!candidate.isInstalled())
+ // continue;
+ // if (candidate.getId().equals(req.getName())) {
+ // if (highestVersion == null || candidate.getVersion().getMajor() > highestVersion.getMajor())
+ // highestVersion = candidate.getVersion();
+ // } else {
+ // //Requesting the upgrade of a virtual package
+ // IProvidedCapability[] prov = candidate.getProvidedCapabilities();
+ // for (int i = 0; i < prov.length; i++) {
+ // if (prov[i].getVersion().equals(VersionRange.emptyRange))
+ // continue;
+ // if (prov[i].getName().equals(req.getName()) && (highestVersion == null || prov[i].getVersion().getMinimum().getMajor() > highestVersion.getMajor()))
+ // highestVersion = prov[i].getVersion().getMinimum();
+ // }
+ // }
+ // }
+ // if (highestVersion == null)
+ // return null;
+ // return new RequiredCapability(req.getName(), new VersionRange(highestVersion, true, Version.maxVersion, true));
+ // }
+
+ /*
+ * Convert the version string to a version object and set it on the IU
+ */
+ private void handleVersion(String line) {
+ currentIU.setVersion(Version.create(cudfPosintToInt(line.substring("version: ".length()))));
+ }
+
+ private String cudfPosintToInt(String posint) {
+ if (posint.startsWith("+")) {
+ return posint.substring(1).trim();
+ }
+ return posint.trim();
+ }
+
+ private void handleDepends(String line) {
+ mergeRequirements(createRequires(line.substring("depends: ".length()), true, false, true));
+ }
+
+ // private void handleRecommends(String line) {
+ // mergeRequirements(createRequires(line.substring("recommends: ".length()), true, true, true));
+ // }
+
+ /*
+ * Conflicts are like depends except NOT'd.
+ */
+ //TODO Remove conflict for now
+ // private void handleConflicts(String line) {
+ // List reqs = createRequires(line.substring("conflicts: ".length()), false, false, false);
+ // List conflicts = new ArrayList();
+ // for (Iterator iter = reqs.iterator(); iter.hasNext();) {
+ // IRequiredCapability req = (IRequiredCapability) iter.next();
+ // if (currentIU.getId().equals(req.getName()) && req.getRange().equals(VersionRange.emptyRange)) {
+ // currentIU.setSingleton(true);
+ // } else {
+ // conflicts.add(new NotRequirement(req));
+ // }
+ // }
+ // mergeRequirements(conflicts);
+ // }
+
+ /*
+ * Set the given list of requirements on teh current IU. Merge if necessary.
+ */
+ private void mergeRequirements(List requirements) {
+ if (currentIU.getRequiredCapabilities() != null) {
+ List<IRequirement> current = currentIU.getRequiredCapabilities();
+ for (IRequirement iRequirement : current) {
+ requirements.add(iRequirement);
+ }
+ }
+ currentIU.setRequirements((IRequiredCapability[]) requirements.toArray(new IRequiredCapability[requirements.size()]));
+ }
+
+ /*
+ * Returns a map where the key is the package name and the value is a Tuple.
+ * If there is more than one entry for a particular package, the extra entries are included
+ * in the extraData field of the Tuple.
+ */
+ private List createPackageList(String line) {
+ StringTokenizer tokenizer = new StringTokenizer(line, ",");
+ List result = new ArrayList(tokenizer.countTokens());
+ while (tokenizer.hasMoreElements()) {
+ result.add(new Tuple(tokenizer.nextToken()));
+ }
+ return result;
+ }
+
+ private List createRequires(String line, boolean expandNotEquals, boolean optional, boolean dependency) {
+ ArrayList ands = new ArrayList();
+ StringTokenizer s = new StringTokenizer(line, ",");
+ String subtoken;
+ while (s.hasMoreElements()) {
+ StringTokenizer subTokenizer = new StringTokenizer(s.nextToken(), "|");
+ if (subTokenizer.countTokens() == 1) { //This token does not contain a |.
+ subtoken = subTokenizer.nextToken().trim();
+ // FIXME should be handled differently in depends and conflicts.
+ if ("true!".equals(subtoken)) {
+ if (dependency)
+ continue;
+ throw new RuntimeException("Cannot have true! in a conflict!!!!!");
+ }
+ if ("false!".equals(subtoken)) {
+ if (!dependency)
+ continue;
+ throw new RuntimeException("Cannot have false! in a dependency!!!!!");
+ }
+ Object o = createRequire(subtoken, expandNotEquals, optional);
+ if (o instanceof IRequiredCapability)
+ ands.add(o);
+ else
+ ands.addAll((Collection) o);
+ continue;
+ }
+
+ IRequiredCapability[] ors = new RequiredCapability[subTokenizer.countTokens()];
+ int i = 0;
+ while (subTokenizer.hasMoreElements()) {
+ ors[i++] = (IRequiredCapability) createRequire(subTokenizer.nextToken().trim(), expandNotEquals, optional);
+ }
+ //TODO Remove OR'ing from requirements for now
+ // ands.add(new ORRequirement(ors, optional));
+ }
+ return ands;
+ }
+
+ private Object createRequire(String nextToken, boolean expandNotEquals, boolean optional) {
+ //>, >=, =, <, <=, !=
+ StringTokenizer expressionTokens = new StringTokenizer(nextToken.trim(), ">=!<", true);
+ int tokenCount = expressionTokens.countTokens();
+
+ if (tokenCount == 1) // a
+ return MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, expressionTokens.nextToken().trim(), VersionRange.emptyRange, null, optional, false, true);
+
+ if (tokenCount == 3) // a > 2, a < 2, a = 2
+ return MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, expressionTokens.nextToken().trim(), createRange3(expressionTokens.nextToken(), expressionTokens.nextToken()), null, optional, false, true);
+
+ if (tokenCount == 4) { //a >= 2, a <=2, a != 2
+ String id = expressionTokens.nextToken().trim();
+ String signFirstChar = expressionTokens.nextToken();
+ expressionTokens.nextToken();//skip second char of the sign
+ String version = expressionTokens.nextToken().trim();
+ if (!("!".equals(signFirstChar))) // a >= 2 a <= 2
+ return MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, id, createRange4(signFirstChar, version), null, optional, false, true);
+
+ // //a != 2 TODO To uncomment
+ // if (expandNotEquals) {
+ // return new ORRequirement(new IRequiredCapability[] {new RequiredCapability(id, createRange3("<", version), optional), new RequiredCapability(id, createRange3(">", version), optional)}, optional);
+ // }
+ ArrayList res = new ArrayList(2);
+ res.add(MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, id, createRange3("<", version), null, optional, false, true));
+ res.add(MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, id, createRange3(">", version), null, optional, false, true));
+ return res;
+ }
+ return null;
+ }
+
+ private VersionRange createRange3(String sign, String versionAsString) {
+ int version = Integer.decode(cudfPosintToInt(versionAsString)).intValue();
+ sign = sign.trim();
+ if (">".equals(sign))
+ return new VersionRange(Version.createOSGi(version, 0, 0), false, Version.MAX_VERSION, false);
+ if ("<".equals(sign))
+ return new VersionRange(Version.emptyVersion, false, Version.createOSGi(version, 0, 0), false);
+ if ("=".equals(sign))
+ return new VersionRange(Version.createOSGi(version, 0, 0), true, Version.createOSGi(version, 0, 0), true);
+ throw new IllegalArgumentException(sign);
+ }
+
+ private VersionRange createRange4(String sign, String versionAsString) {
+ int version = Integer.decode(cudfPosintToInt(versionAsString)).intValue();
+ if (">".equals(sign)) //THIS IS FOR >=
+ return new VersionRange(Version.createOSGi(version, 0, 0), true, Version.MAX_VERSION, false);
+ if ("<".equals(sign)) //THIS IS FOR <=
+ return new VersionRange(Version.emptyVersion, false, Version.createOSGi(version, 0, 0), true);
+ return null;
+ }
+
+ private IProvidedCapability createProvidedCapability(Tuple tuple) {
+ //At this point the parser only deal with standard provided capabilities and not ranges like cudf does.
+ assert tuple.extraData == null;
+ assert tuple.operator == null;
+ return MetadataFactory.createProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, tuple.name, Version.create(tuple.version));
+ // Set extraData = tuple.extraData;
+ // one constraint so simply return the capability
+ // if (extraData == null)
+ // return new ProvidedCapability(tuple.name, createVersionRange(tuple.operator, tuple.version));
+ // // 2 constraints (e.g. a>=1, a<4) so create a real range like a[1,4)
+ // if (extraData.size() == 1)
+ // return new ProvidedCapability(tuple.name, createVersionRange(tuple, (Tuple) extraData.iterator().next()));
+ // // TODO merge more than 2 requirements (a>2, a<4, a>3)
+ // return new ProvidedCapability(tuple.name, createVersionRange(tuple.operator, tuple.version));
+ }
+
+ /*
+ * Create and return a version range object which merges the 2 given versions and operators.
+ * e.g a>=1 and a<4 becomes a[1,4)
+ */
+ // private VersionRange createVersionRange(Tuple t1, Tuple t2) {
+ // Version one = Version.parseVersion(t1.version);
+ // Version two = Version.parseVersion(t2.version);
+ // if (one.compareTo(two) < 0) {
+ // return new VersionRange(one, include(t1.operator), two, include(t2.operator));
+ // } else if (one.compareTo(two) == 0) {
+ // return new VersionRange(one, include(t1.operator), one, include(t1.operator));
+ // } else if (one.compareTo(two) > 0) {
+ // return new VersionRange(two, include(t2.operator), one, include(t1.operator));
+ // }
+ // // should never reach this. avoid compile error.
+ // return null;
+ // }
+
+ /*
+ * Helper method for when we are creating version ranges and calculating "includeMin/Max".
+ */
+ // private boolean include(String operator) {
+ // return "=".equals(operator) || "<=".equals(operator) || ">=".equals(operator);
+ // }
+ //
+ // /*
+ // * Create and return a version range based on the given operator and number. Note that != is
+ // * handled elsewhere.
+ // */
+ // private VersionRange createVersionRange(String operator, String number) {
+ // if (operator == null || number == null)
+ // return VersionRange.emptyRange;
+ // if ("=".equals(operator))
+ // return new VersionRange('[' + number + ',' + number + ']');
+ // if ("<".equals(operator))
+ // return new VersionRange("[0," + number + ')');
+ // if (">".equals(operator))
+ // return new VersionRange('(' + number + ',' + Integer.MAX_VALUE + ']');
+ // if ("<=".equals(operator))
+ // return new VersionRange("[0," + number + ']');
+ // if (">=".equals(operator))
+ // return new VersionRange('[' + number + ',' + Integer.MAX_VALUE + ']');
+ // return VersionRange.emptyRange;
+ // }
+
+ // package name matches: "^[a-zA-Z0-9+./@()%-]+$"
+ private void handlePackage(String readLine) {
+ currentIU = new MetadataFactory.InstallableUnitDescription();
+ currentIU.setId(readLine.substring("package: ".length()).trim());
+ }
+
+ private void handleProvides(String line) {
+ line = line.substring("provides: ".length());
+ List pkgs = createPackageList(line);
+ IProvidedCapability[] providedCapabilities = new ProvidedCapability[pkgs.size() + 2];
+ int i = 0;
+ for (Iterator iter = pkgs.iterator(); iter.hasNext();) {
+ providedCapabilities[i++] = createProvidedCapability((Tuple) iter.next());
+ }
+ providedCapabilities[i++] = MetadataFactory.createProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, currentIU.getId(), currentIU.getVersion());
+ providedCapabilities[i++] = MetadataFactory.createProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, currentIU.getId(), currentIU.getVersion());
+ currentIU.setCapabilities(providedCapabilities);
+ }
+
+ // // copied from ProfileSynchronizer
+ // private void debug(ProfileChangeRequest request) {
+ // if (!DEBUG || request == null)
+ // return;
+ // // Log.println("\nProfile Change Request:");
+ // // InstallableUnit[] toAdd = request.getAddedInstallableUnit();
+ // // if (toAdd == null || toAdd.length == 0) {
+ // // Log.println("No installable units to add.");
+ // // } else {
+ // // for (int i = 0; i < toAdd.length; i++)
+ // // Log.println("Adding IU: " + toAdd[i].getId() + ' ' + toAdd[i].getVersion());
+ // // }
+ // // Map propsToAdd = request.getInstallableUnitProfilePropertiesToAdd();
+ // // if (propsToAdd == null || propsToAdd.isEmpty()) {
+ // // Log.println("No IU properties to add.");
+ // // } else {
+ // // for (Iterator iter = propsToAdd.keySet().iterator(); iter.hasNext();) {
+ // // Object key = iter.next();
+ // // Log.println("Adding IU property: " + key + "->" + propsToAdd.get(key));
+ // // }
+ // // }
+ // //
+ // // InstallableUnit[] toRemove = request.getRemovedInstallableUnits();
+ // // if (toRemove == null || toRemove.length == 0) {
+ // // Log.println("No installable units to remove.");
+ // // } else {
+ // // for (int i = 0; i < toRemove.length; i++)
+ // // Log.println("Removing IU: " + toRemove[i].getId() + ' ' + toRemove[i].getVersion());
+ // // }
+ // // Map propsToRemove = request.getInstallableUnitProfilePropertiesToRemove();
+ // // if (propsToRemove == null || propsToRemove.isEmpty()) {
+ // // Log.println("No IU properties to remove.");
+ // // } else {
+ // // for (Iterator iter = propsToRemove.keySet().iterator(); iter.hasNext();) {
+ // // Object key = iter.next();
+ // // Log.println("Removing IU property: " + key + "->" + propsToRemove.get(key));
+ // // }
+ // // }
+ // }
+
+ // dump info to console
+ private void debug(InstallableUnit unit) {
+ // if (!DEBUG)
+ // return;
+ // Log.println("\nInstallableUnit: " + unit.getId());
+ // Log.println("Version: " + unit.getVersion());
+ // if (unit.isInstalled())
+ // Log.println("Installed: true");
+ // IRequiredCapability[] reqs = unit.getRequiredCapabilities();
+ // for (int i = 0; i < reqs.length; i++) {
+ // Log.println("Requirement: " + reqs[i]);
+ // }
+ }
+
+ public IInstallableUnit getIU() {
+ assert allIUs.size() == 1;
+ return (IInstallableUnit) allIUs.get(0);
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/LuckyHelper.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/LuckyHelper.java
new file mode 100644
index 000000000..70951f0ad
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/LuckyHelper.java
@@ -0,0 +1,87 @@
+package org.eclipse.equinox.p2.tests.planner;
+
+import java.util.*;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
+import org.eclipse.equinox.internal.p2.metadata.query.UpdateQuery;
+import org.eclipse.equinox.p2.engine.*;
+import org.eclipse.equinox.p2.engine.query.IUProfilePropertyQuery;
+import org.eclipse.equinox.p2.metadata.*;
+import org.eclipse.equinox.p2.planner.*;
+import org.eclipse.equinox.p2.query.*;
+
+public class LuckyHelper {
+ ProfileChangeRequest computeProfileChangeRequest(IProfile profile, IPlanner planner, ProfileChangeRequest request, ProvisioningContext context, IProgressMonitor monitor) {
+ // IProfileRegistry profileRegistry = (IProfileRegistry) session.getProvisioningAgent().getService(IProfileRegistry.SERVICE_NAME);
+ IPlanner plan = planner; //(IPlanner) session.getProvisioningAgent().getService(IPlanner.SERVICE_NAME);
+ IProfile prof = profile; //profileRegistry.getProfile(getProfileId());
+
+ final String INCLUSION_RULES = "org.eclipse.equinox.p2.internal.inclusion.rules"; //$NON-NLS-1$
+ final String INCLUSION_OPTIONAL = "OPTIONAL"; //$NON-NLS-1$
+ final String INCLUSION_STRICT = "STRICT"; //$NON-NLS-1$
+
+ IQueryResult<IInstallableUnit> strictRoots = prof.query(new IUProfilePropertyQuery(INCLUSION_RULES, INCLUSION_STRICT), null);
+ IQueryResult<IInstallableUnit> optionalRoots = prof.query(new IUProfilePropertyQuery(INCLUSION_RULES, INCLUSION_OPTIONAL), null);
+ Set<IInstallableUnit> tmpRoots = new HashSet<IInstallableUnit>(strictRoots.toUnmodifiableSet());
+ tmpRoots.addAll(optionalRoots.toUnmodifiableSet());
+ CollectionResult<IInstallableUnit> allRoots = new CollectionResult<IInstallableUnit>(tmpRoots);
+
+ request = (ProfileChangeRequest) plan.createChangeRequest(prof);
+ Collection<IRequirement> limitingRequirements = new ArrayList<IRequirement>();
+
+ for (Iterator<IInstallableUnit> iterator = allRoots.query(QueryUtil.ALL_UNITS, null).iterator(); iterator.hasNext();) {
+ IInstallableUnit currentlyInstalled = iterator.next();
+
+ //find all the potential updates for the currentlyInstalled iu
+ IQueryResult<IInstallableUnit> updatesAvailable = plan.updatesFor(currentlyInstalled, context, null);
+ for (Iterator<IInstallableUnit> iterator2 = updatesAvailable.iterator(); iterator2.hasNext();) {
+ IInstallableUnit update = iterator2.next();
+ request.add(update);
+ request.setInstallableUnitInclusionRules(update, ProfileInclusionRules.createOptionalInclusionRule(update));
+ }
+ if (!updatesAvailable.isEmpty()) {
+ //force the original IU to optional, but make sure that the solution at least includes it
+ request.setInstallableUnitInclusionRules(currentlyInstalled, ProfileInclusionRules.createOptionalInclusionRule(currentlyInstalled));
+ limitingRequirements.add(MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, currentlyInstalled.getId(), new VersionRange(currentlyInstalled.getVersion(), true, Version.MAX_VERSION, true), null, false, false));
+ }
+ }
+
+ IProvisioningPlan updateFinderPlan = plan.getProvisioningPlan(request, context, null);
+ if (updateFinderPlan.getAdditions().query(QueryUtil.ALL_UNITS, null).isEmpty()) {
+ return null;
+ }
+
+ //Take into account all the removals
+ IProfileChangeRequest finalChangeRequest = plan.createChangeRequest(prof);
+ IQueryResult<IInstallableUnit> removals = updateFinderPlan.getRemovals().query(QueryUtil.ALL_UNITS, null);
+ for (Iterator<IInstallableUnit> iterator = removals.iterator(); iterator.hasNext();) {
+ IInstallableUnit iu = iterator.next();
+ if (!allRoots.query(QueryUtil.createIUQuery(iu), null).isEmpty()) {
+ finalChangeRequest.remove(iu);
+ }
+ }
+
+ //Take into account the additions for stricts
+ for (Iterator<IInstallableUnit> iterator = strictRoots.iterator(); iterator.hasNext();) {
+ IInstallableUnit formerRoot = iterator.next();
+ IQueryResult<IInstallableUnit> update = updateFinderPlan.getAdditions().query(new UpdateQuery(formerRoot), null);
+ if (!update.isEmpty())
+ finalChangeRequest.addAll(update.toUnmodifiableSet());
+ }
+
+ //Take into account the additions for optionals
+ for (Iterator<IInstallableUnit> iterator = optionalRoots.iterator(); iterator.hasNext();) {
+ IInstallableUnit formerRoot = iterator.next();
+ IQueryResult<IInstallableUnit> update = updateFinderPlan.getAdditions().query(new UpdateQuery(formerRoot), null);
+ if (!update.isEmpty()) {
+ for (Iterator<IInstallableUnit> it = update.iterator(); it.hasNext();) {
+ IInstallableUnit updatedOptionalIU = it.next();
+ finalChangeRequest.add(updatedOptionalIU);
+ finalChangeRequest.setInstallableUnitInclusionRules(updatedOptionalIU, ProfileInclusionRules.createOptionalInclusionRule(updatedOptionalIU));
+ }
+ }
+ }
+ return (ProfileChangeRequest) finalChangeRequest;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/LuckyTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/LuckyTest.java
new file mode 100644
index 000000000..ca9c08831
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/LuckyTest.java
@@ -0,0 +1,51 @@
+package org.eclipse.equinox.p2.tests.planner;
+
+import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
+import org.eclipse.equinox.p2.engine.*;
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.planner.IPlanner;
+import org.eclipse.equinox.p2.tests.*;
+
+public class LuckyTest extends AbstractProvisioningTest {
+ @IUDescription(content = "package: sdk \n" + "singleton: true\n" + "version: 1 \n" + "depends: platform = 1")
+ public IInstallableUnit sdk1;
+
+ @IUDescription(content = "package: platform \n" + "singleton: true\n" + "version: 1 \n")
+ public IInstallableUnit platform1;
+
+ @IUDescription(content = "package: sdk \n" + "singleton: true\n" + "version: 2 \n" + "depends: platform = 2")
+ public IInstallableUnit sdk2;
+
+ @IUDescription(content = "package: platform \n" + "singleton: true\n" + "version: 2 \n")
+ public IInstallableUnit platform2;
+
+ IProfile profile = createProfile("TestProfile." + getName());
+
+ private IPlanner planner;
+
+ private IEngine engine;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ IULoader.loadIUs(this);
+ createTestMetdataRepository(new IInstallableUnit[] {sdk1, platform1, sdk2, platform2});
+ System.out.println(sdk1);
+ System.out.println(platform1);
+ System.out.println(sdk2);
+ System.out.println(platform2);
+ planner = createPlanner();
+ engine = createEngine();
+ assertOK(install(profile, new IInstallableUnit[] {sdk1}, true, planner, engine));
+ }
+
+ public void testInstallSDK2() {
+ assertNotOK(install(profile, new IInstallableUnit[] {platform2}, true, planner, engine));
+ ProfileChangeRequest request = new ProfileChangeRequest(profile);
+ request.add(platform2);
+ ProfileChangeRequest res = new LuckyHelper().computeProfileChangeRequest(profile, planner, request, new ProvisioningContext(getAgent()), getMonitor());
+ assertTrue(res.getAdditions().contains(sdk2));
+ assertTrue(res.getRemovals().contains(sdk1));
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/LuckyTest2.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/LuckyTest2.java
new file mode 100644
index 000000000..9a64d5a10
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/LuckyTest2.java
@@ -0,0 +1,57 @@
+package org.eclipse.equinox.p2.tests.planner;
+
+import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
+import org.eclipse.equinox.p2.engine.*;
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.planner.IPlanner;
+import org.eclipse.equinox.p2.tests.*;
+
+public class LuckyTest2 extends AbstractProvisioningTest {
+ @IUDescription(content = "package: sdk \n" + "singleton: true\n" + "version: 1 \n" + "depends: platform = 1")
+ public IInstallableUnit sdk1;
+
+ @IUDescription(content = "package: platform \n" + "singleton: true\n" + "version: 1 \n")
+ public IInstallableUnit platform1;
+
+ @IUDescription(content = "package: sdk \n" + "singleton: true\n" + "version: 2 \n" + "depends: platform = 2")
+ public IInstallableUnit sdk2;
+
+ @IUDescription(content = "package: platform \n" + "singleton: true\n" + "version: 2 \n")
+ public IInstallableUnit platform2;
+
+ @IUDescription(content = "package: egit \n" + "singleton: true\n" + "version: 1 \n")
+ public IInstallableUnit egit1;
+
+ IProfile profile = createProfile("TestProfile." + getName());
+
+ private IPlanner planner;
+
+ private IEngine engine;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ IULoader.loadIUs(this);
+ createTestMetdataRepository(new IInstallableUnit[] {sdk1, platform1, sdk2, platform2, egit1});
+ planner = createPlanner();
+ engine = createEngine();
+ assertOK(install(profile, new IInstallableUnit[] {sdk1, egit1}, true, planner, engine));
+ }
+
+ public void testInstallSDK2() {
+ assertNotOK(install(profile, new IInstallableUnit[] {platform2}, true, planner, engine));
+ ProfileChangeRequest request = new ProfileChangeRequest(profile);
+ request.add(platform2);
+
+ ProfileChangeRequest res = new LuckyHelper().computeProfileChangeRequest(profile, planner, request, new ProvisioningContext(getAgent()), getMonitor());
+ assertEquals(1, res.getAdditions().size());
+ assertTrue(res.getAdditions().contains(sdk2));
+ assertEquals(1, res.getRemovals().size());
+ assertTrue(res.getRemovals().contains(sdk1));
+
+ assertOK(install(res, planner, engine));
+ assertProfileContains("validate new profile", profile, new IInstallableUnit[] {sdk2, platform2, egit1});
+ assertEquals("STRICT", profile.getInstallableUnitProperty(sdk2, "org.eclipse.equinox.p2.internal.inclusion.rules"));
+ assertEquals("STRICT", profile.getInstallableUnitProperty(egit1, "org.eclipse.equinox.p2.internal.inclusion.rules"));
+ }
+}

Back to the top