summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPascal Rapicault (JBoss)2013-02-28 21:03:16 (EST)
committerPascal Rapicault2013-03-23 23:11:45 (EDT)
commit251702b2afa7efdf3652750e667007a2878ce6bf (patch)
tree0c9e3df780c267ee12fe2daa8c5629a4f1f4cad3
parentbb5713948807de4101b7043632b6f46397786629 (diff)
downloadrt.equinox.p2-251702b2afa7efdf3652750e667007a2878ce6bf.zip
rt.equinox.p2-251702b2afa7efdf3652750e667007a2878ce6bf.tar.gz
rt.equinox.p2-251702b2afa7efdf3652750e667007a2878ce6bf.tar.bz2
Add remediation page
When an operation can't succeed, the error page is replaced by a dialog letting the user pick a better solution. This is enabled in all major workflows. At the projector level, it features a new encoding for optionality and a new way of defining optimization functions.
-rw-r--r--bundles/org.eclipse.equinox.p2.director/META-INF/MANIFEST.MF6
-rw-r--r--bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/OptimizationFunction.java31
-rw-r--r--bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/Projector.java123
-rw-r--r--bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/SimplePlanner.java17
-rw-r--r--bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/UserDefinedOptimizationFunction.java198
-rw-r--r--bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/IQueryResult.java2
-rw-r--r--bundles/org.eclipse.equinox.p2.operations/META-INF/MANIFEST.MF1
-rw-r--r--bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/IStatusCodes.java1
-rw-r--r--bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/Messages.java5
-rw-r--r--bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/PlanAnalyzer.java9
-rw-r--r--bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/RequestFlexer.java344
-rw-r--r--bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/ResolutionResult.java4
-rw-r--r--bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/messages.properties8
-rw-r--r--bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/RelaxedUpdateInstallOperation.java112
-rw-r--r--bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/RemediationOperation.java218
-rw-r--r--bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/Remedy.java55
-rw-r--r--bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/RemedyConfig.java57
-rw-r--r--bundles/org.eclipse.equinox.p2.tests.ui/src/org/eclipse/equinox/p2/tests/ui/AbstractProvisioningUITest.java4
-rw-r--r--bundles/org.eclipse.equinox.p2.tests.ui/src/org/eclipse/equinox/p2/tests/ui/dialogs/RemediationTest.java157
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/AbstractProvisioningTest.java9
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/ReducedCUDFParser.java1
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/AllAnyVersionTests.java27
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/Bug306279c.java2
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/JBoss.java56
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerIUProperties.java198
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerOneInstalledOneBeingInstalled.java175
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerOneInstalledReplacingIt.java102
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerOneInstalledTwoBeingInstalled.java171
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerRequestWithOptionalInstall.java122
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerRequestWithRemoval.java86
-rw-r--r--bundles/org.eclipse.equinox.p2.ui.sdk/META-INF/MANIFEST.MF1
-rw-r--r--bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/UpdateHandler.java35
-rw-r--r--bundles/org.eclipse.equinox.p2.ui/icons/obj/iu_add.gifbin0 -> 318 bytes
-rw-r--r--bundles/org.eclipse.equinox.p2.ui/icons/obj/iu_remove.gifbin0 -> 351 bytes
-rw-r--r--bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIActivator.java5
-rw-r--r--bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIImages.java5
-rw-r--r--bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIMessages.java18
-rw-r--r--bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/ProfileModificationAction.java3
-rw-r--r--bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/UpdateAction.java47
-rw-r--r--bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstallWizard.java37
-rw-r--r--bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstallWizardPage.java7
-rw-r--r--bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/PreselectedIUInstallWizard.java10
-rw-r--r--bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ProvisioningOperationWizard.java123
-rw-r--r--bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/RemediationPage.java343
-rw-r--r--bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ResolutionResultsWizardPage.java34
-rw-r--r--bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/SelectableIUsPage.java39
-rw-r--r--bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/UninstallWizard.java10
-rw-r--r--bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/UpdateWizard.java51
-rw-r--r--bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/messages.properties16
-rw-r--r--bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/model/AvailableIUElement.java14
-rw-r--r--bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/p2/ui/ProvisioningUI.java28
51 files changed, 2752 insertions, 375 deletions
diff --git a/bundles/org.eclipse.equinox.p2.director/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.director/META-INF/MANIFEST.MF
index f9ad8f3..f9d9aae 100644
--- a/bundles/org.eclipse.equinox.p2.director/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.director/META-INF/MANIFEST.MF
@@ -23,10 +23,10 @@ Export-Package: org.eclipse.equinox.internal.p2.director;
org.eclipse.equinox.p2.installer",
org.eclipse.equinox.p2.planner;version="2.0.0"
Require-Bundle: org.eclipse.equinox.common;bundle-version="[3.3.0,4.0.0)",
- org.sat4j.core;bundle-version="[2.2.0,2.4.0)",
- org.sat4j.pb;bundle-version="[2.2.0,2.4.0)",
org.eclipse.core.jobs;bundle-version="[3.3.0,4.0.0)",
- org.eclipse.equinox.p2.metadata;bundle-version="[2.0.0,3.0.0)"
+ org.eclipse.equinox.p2.metadata;bundle-version="[2.0.0,3.0.0)",
+ org.sat4j.pb;bundle-version="[2.3.3,3.0.0)",
+ org.sat4j.core;bundle-version="[2.3.3,3.0.0)"
Bundle-RequiredExecutionEnvironment: J2SE-1.5,
J2SE-1.4,
CDC-1.1/Foundation-1.1
diff --git a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/OptimizationFunction.java b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/OptimizationFunction.java
index 55cc381..c29fe88 100644
--- a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/OptimizationFunction.java
+++ b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/OptimizationFunction.java
@@ -23,17 +23,14 @@ public class OptimizationFunction {
private IQueryable<IInstallableUnit> picker;
private IInstallableUnit selectionContext;
- private Map<String, Map<Version, IInstallableUnit>> slice; //The IUs that have been considered to be part of the problem
- private int numberOfInstalledIUs;
+ protected Map<String, Map<Version, IInstallableUnit>> slice; //The IUs that have been considered to be part of the problem
+ private int numberOfInstalledIUs; //TODO this should be renamed to consideredIUs or sliceSize
private IQueryable<IInstallableUnit> lastState;
- private List<AbstractVariable> abstractVariables;
+ private List<AbstractVariable> optionalRequirementVariable;
- // private IInstallableUnit[] alreadyExistingRoots;
- // private IQueryable<IInstallableUnit> beingInstalled;
-
- public OptimizationFunction(IQueryable<IInstallableUnit> lastState, List<AbstractVariable> abstractVariables, IQueryable<IInstallableUnit> picker, IInstallableUnit selectionContext, Map<String, Map<Version, IInstallableUnit>> slice) {
+ public OptimizationFunction(IQueryable<IInstallableUnit> lastState, List<AbstractVariable> abstractVariables, List<AbstractVariable> optionalRequirementVariable, IQueryable<IInstallableUnit> picker, IInstallableUnit selectionContext, Map<String, Map<Version, IInstallableUnit>> slice) {
this.lastState = lastState;
- this.abstractVariables = abstractVariables;
+ this.optionalRequirementVariable = optionalRequirementVariable;
this.picker = picker;
this.selectionContext = selectionContext;
this.slice = slice;
@@ -44,7 +41,7 @@ public class OptimizationFunction {
numberOfInstalledIUs = sizeOf(lastState);
List<WeightedObject<? extends Object>> weightedObjects = new ArrayList<WeightedObject<? extends Object>>();
- Set<IInstallableUnit> transitiveClosure;
+ Set<IInstallableUnit> transitiveClosure; //The transitive closure of the IUs we are adding (this also means updating)
if (newRoots.isEmpty()) {
transitiveClosure = CollectionUtils.emptySet();
} else {
@@ -63,13 +60,15 @@ public class OptimizationFunction {
for (Entry<String, Map<Version, IInstallableUnit>> entry : s) {
List<IInstallableUnit> conflictingEntries = new ArrayList<IInstallableUnit>(entry.getValue().values());
if (conflictingEntries.size() == 1) {
+ //Only one IU exists with the namespace.
IInstallableUnit iu = conflictingEntries.get(0);
if (iu != metaIu) {
weightedObjects.add(WeightedObject.newWO(iu, POWER));
}
continue;
}
- // IUs are sorted from highest version to lowest.
+
+ // Set the weight such that things that are already installed are not updated
Collections.sort(conflictingEntries, Collections.reverseOrder());
BigInteger weight = POWER;
// have we already found a version that is already installed?
@@ -96,14 +95,15 @@ public class OptimizationFunction {
// maximal weight used so far.
maxWeight = maxWeight.multiply(POWER).multiply(BigInteger.valueOf(s.size()));
- // Add the abstract variables
- BigInteger abstractWeight = maxWeight.negate();
- for (AbstractVariable var : abstractVariables) {
- weightedObjects.add(WeightedObject.newWO(var, abstractWeight));
+ // Add the optional variables
+ BigInteger optionalVarWeight = maxWeight.negate();
+ for (AbstractVariable var : optionalRequirementVariable) {
+ weightedObjects.add(WeightedObject.newWO(var, optionalVarWeight));
}
maxWeight = maxWeight.multiply(POWER).add(BigInteger.ONE);
+ //Now we deal the optional IUs,
BigInteger optionalWeight = maxWeight.negate();
long countOptional = 1;
List<IInstallableUnit> requestedPatches = new ArrayList<IInstallableUnit>();
@@ -117,12 +117,11 @@ public class OptimizationFunction {
if (match instanceof IInstallableUnitPatch) {
requestedPatches.add(match);
countOptional = countOptional + 1;
- } else {
- weightedObjects.add(WeightedObject.newWO(match, optionalWeight));
}
}
}
+ // and we make sure that patches are always favored
BigInteger patchWeight = maxWeight.multiply(POWER).multiply(BigInteger.valueOf(countOptional)).negate();
for (Iterator<IInstallableUnit> iterator = requestedPatches.iterator(); iterator.hasNext();) {
weightedObjects.add(WeightedObject.newWO(iterator.next(), patchWeight));
diff --git a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/Projector.java b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/Projector.java
index 59e8eb2..ba401bb 100644
--- a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/Projector.java
+++ b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/Projector.java
@@ -11,6 +11,7 @@
* Jed Anderson - switch from opb files to API calls to DependencyHelper in bug 200380
* Sonatype, Inc. - ongoing development
* Rapicorp, Inc. - split the optimization function
+ * Red Hat, Inc. - support for remediation page
******************************************************************************/
package org.eclipse.equinox.internal.p2.director;
@@ -27,9 +28,10 @@ import org.eclipse.equinox.p2.metadata.*;
import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
import org.eclipse.equinox.p2.query.*;
import org.eclipse.osgi.util.NLS;
+import org.sat4j.minisat.restarts.LubyRestarts;
import org.sat4j.pb.*;
-import org.sat4j.pb.tools.DependencyHelper;
-import org.sat4j.pb.tools.WeightedObject;
+import org.sat4j.pb.core.PBSolverResolution;
+import org.sat4j.pb.tools.*;
import org.sat4j.specs.*;
/**
@@ -53,7 +55,7 @@ public class Projector {
private IQueryable<IInstallableUnit> picker;
private QueryableArray patches;
- private Map<IInstallableUnit, AbstractVariable> noopVariables; //key IU, value AbstractVariable
+ private List<AbstractVariable> allOptionalAbstractRequirements;
private List<AbstractVariable> abstractVariables;
private Map<String, Map<Version, IInstallableUnit>> slice; //The IUs that have been considered to be part of the problem
@@ -78,6 +80,9 @@ public class Projector {
private Map<IInstallableUnit, AbstractVariable> nonGreedyVariables = new HashMap<IInstallableUnit, AbstractVariable>();
private Map<AbstractVariable, List<Object>> nonGreedyProvider = new HashMap<AbstractVariable, List<Object>>(); //Keeps track of all the "object" that provide an IU that is non greedly requested
+ private boolean emptyBecauseFiltered;
+ private boolean userDefinedFunction;
+
static class AbstractVariable {
// private String name;
@@ -154,24 +159,19 @@ public class Projector {
public Projector(IQueryable<IInstallableUnit> q, Map<String, String> context, Set<IInstallableUnit> nonGreedyIUs, boolean considerMetaRequirements) {
picker = q;
- noopVariables = new HashMap<IInstallableUnit, AbstractVariable>();
slice = new HashMap<String, Map<Version, IInstallableUnit>>();
selectionContext = InstallableUnit.contextIU(context);
abstractVariables = new ArrayList<AbstractVariable>();
+ allOptionalAbstractRequirements = new ArrayList<AbstractVariable>();
result = new MultiStatus(DirectorActivator.PI_DIRECTOR, IStatus.OK, Messages.Planner_Problems_resolving_plan, null);
assumptions = new ArrayList<Object>();
this.nonGreedyIUs = nonGreedyIUs;
this.considerMetaRequirements = considerMetaRequirements;
}
- // protected boolean isInstalled(IInstallableUnit iu) {
- // return !lastState.query(QueryUtil.createIUQuery(iu), null).isEmpty();
- // }
-
@SuppressWarnings("unchecked")
public void encode(IInstallableUnit entryPointIU, IInstallableUnit[] alreadyExistingRoots, IQueryable<IInstallableUnit> installedIUs, Collection<IInstallableUnit> newRoots, IProgressMonitor monitor) {
alreadyInstalledIUs = Arrays.asList(alreadyExistingRoots);
- // numberOfInstalledIUs = sizeOf(installedIUs);
lastState = installedIUs;
this.entryPoint = entryPointIU;
try {
@@ -184,7 +184,14 @@ public class Projector {
if (DEBUG_ENCODING) {
solver = new UserFriendlyPBStringSolver<Object>();
} else {
- solver = SolverFactory.newEclipseP2();
+ if (userDefinedFunction) {
+ PBSolverResolution mysolver = SolverFactory.newCompetPBResLongWLMixedConstraintsObjectiveExpSimp();
+ mysolver.setSimplifier(mysolver.SIMPLE_SIMPLIFICATION);
+ mysolver.setRestartStrategy(new LubyRestarts(512));
+ solver = mysolver;
+ } else {
+ solver = SolverFactory.newEclipseP2();
+ }
}
int timeout = DEFAULT_SOLVER_TIMEOUT;
String timeoutString = null;
@@ -204,10 +211,13 @@ public class Projector {
solver.setTimeoutOnConflicts(timeout);
IQueryResult<IInstallableUnit> queryResult = picker.query(QueryUtil.createIUAnyQuery(), null);
if (DEBUG_ENCODING) {
- dependencyHelper = new DependencyHelper<Object, Explanation>(solver, false);
+ dependencyHelper = new LexicoHelper<Object, Explanation>(solver, false);
((UserFriendlyPBStringSolver<Object>) solver).setMapping(dependencyHelper.getMappingToDomain());
} else {
- dependencyHelper = new DependencyHelper<Object, Explanation>(solver);
+ if (userDefinedFunction)
+ dependencyHelper = new LexicoHelper<Object, Explanation>(solver);
+ else
+ dependencyHelper = new DependencyHelper<Object, Explanation>(solver);
}
List<IInstallableUnit> iusToOrder = new ArrayList<IInstallableUnit>(queryResult.toSet());
Collections.sort(iusToOrder);
@@ -255,13 +265,28 @@ public class Projector {
}
+ private void createOptimizationFunction(IInstallableUnit entryPointIU, Collection<IInstallableUnit> newRoots) {
+ if (!userDefinedFunction) {
+ createStandardOptimizationFunction(entryPointIU, newRoots);
+ } else {
+ createUserDefinedOptimizationFunction(entryPointIU, newRoots);
+ }
+ }
+
//Create an optimization function favoring the highest version of each IU
- private void createOptimizationFunction(IInstallableUnit metaIu, Collection<IInstallableUnit> newRoots) {
- List<WeightedObject<? extends Object>> weights = new OptimizationFunction(lastState, abstractVariables, picker, selectionContext, slice).createOptimizationFunction(metaIu, newRoots);
+ private void createStandardOptimizationFunction(IInstallableUnit entryPointIU, Collection<IInstallableUnit> newRoots) {
+ List<WeightedObject<? extends Object>> weights = new OptimizationFunction(lastState, abstractVariables, allOptionalAbstractRequirements, picker, selectionContext, slice).createOptimizationFunction(entryPointIU, newRoots);
+ createObjectiveFunction(weights);
+ }
+
+ private void createUserDefinedOptimizationFunction(IInstallableUnit entryPointIU, Collection<IInstallableUnit> newRoots) {
+ List<WeightedObject<? extends Object>> weights = new UserDefinedOptimizationFunction(lastState, abstractVariables, allOptionalAbstractRequirements, picker, selectionContext, slice, dependencyHelper, alreadyInstalledIUs).createOptimizationFunction(entryPointIU, newRoots);
createObjectiveFunction(weights);
}
private void createObjectiveFunction(List<WeightedObject<? extends Object>> weightedObjects) {
+ if (weightedObjects == null)
+ return;
if (DEBUG) {
StringBuffer b = new StringBuffer();
for (WeightedObject<? extends Object> object : weightedObjects) {
@@ -399,6 +424,7 @@ public class Projector {
addNonGreedyProvider(getNonGreedyVariable(current), abs);
}
}
+ optionalAbstractRequirements.add(abs);
} else {
abs = getAbstractVariable(req, false);
List<Object> newConstraint = new ArrayList<Object>();
@@ -408,7 +434,6 @@ public class Projector {
}
createImplication(new Object[] {abs, iu}, newConstraint, Explanation.OPTIONAL_REQUIREMENT);
}
- optionalAbstractRequirements.add(abs);
}
}
}
@@ -425,11 +450,9 @@ public class Projector {
private void expandRequirements(Collection<IRequirement> reqs, IInstallableUnit iu, boolean isRootIu) throws ContradictionException {
if (reqs.isEmpty())
return;
- List<AbstractVariable> optionalAbstractRequirements = new ArrayList<AbstractVariable>();
for (IRequirement req : reqs) {
- expandRequirement(req, iu, optionalAbstractRequirements, isRootIu);
+ expandRequirement(req, iu, allOptionalAbstractRequirements, isRootIu);
}
- createOptionalityExpression(iu, optionalAbstractRequirements);
}
public void processIU(IInstallableUnit iu, boolean isRootIU) throws ContradictionException {
@@ -452,7 +475,7 @@ public class Projector {
expandRequirements(getRequiredCapabilities(iu), iu, isRootIU);
} else {
//Patches are applicable to the IU
- expandRequirementsWithPatches(iu, applicablePatches, isRootIU);
+ expandRequirementsWithPatches(iu, applicablePatches, allOptionalAbstractRequirements, isRootIU);
}
}
@@ -480,7 +503,7 @@ public class Projector {
Object left;
}
- private void expandRequirementsWithPatches(IInstallableUnit iu, IQueryResult<IInstallableUnit> applicablePatches, boolean isRootIu) throws ContradictionException {
+ private void expandRequirementsWithPatches(IInstallableUnit iu, IQueryResult<IInstallableUnit> applicablePatches, List<AbstractVariable> optionalAbstractRequirements, boolean isRootIu) throws ContradictionException {
//Unmodified dependencies
Collection<IRequirement> iuRequirements = getRequiredCapabilities(iu);
Map<IRequirement, List<IInstallableUnitPatch>> unchangedRequirements = new HashMap<IRequirement, List<IInstallableUnitPatch>>(iuRequirements.size());
@@ -496,7 +519,6 @@ public class Projector {
// noop(IU)-> ~ABS
// IU -> (noop(IU) or ABS)
// Therefore we only need one optional requirement statement per IU
- List<AbstractVariable> optionalAbstractRequirements = new ArrayList<AbstractVariable>();
for (int i = 0; i < reqs.length; i++) {
//The requirement is unchanged
if (reqs[i][0] == reqs[i][1]) {
@@ -568,6 +590,7 @@ public class Projector {
addNonGreedyProvider(getNonGreedyVariable(current), abs);
}
}
+ optionalAbstractRequirements.add(abs);
} else {
abs = getAbstractVariable(req, false);
List<Object> newConstraint = new ArrayList<Object>(matches.size());
@@ -577,7 +600,6 @@ public class Projector {
}
createImplication(new Object[] {patch, abs, iu}, newConstraint, Explanation.OPTIONAL_REQUIREMENT);
}
- optionalAbstractRequirements.add(abs);
}
}
}
@@ -683,7 +705,6 @@ public class Projector {
}
}
}
- createOptionalityExpression(iu, optionalAbstractRequirements);
}
// Fix: now create the pending non-patch requirements based on the full set of patches
@@ -691,7 +712,6 @@ public class Projector {
createImplication(pending.left, pending.matches, pending.explanation);
}
- List<AbstractVariable> optionalAbstractRequirements = new ArrayList<AbstractVariable>();
for (Entry<IRequirement, List<IInstallableUnitPatch>> entry : unchangedRequirements.entrySet()) {
List<IInstallableUnitPatch> patchesApplied = entry.getValue();
Iterator<IInstallableUnit> allPatches = applicablePatches.iterator();
@@ -779,7 +799,6 @@ public class Projector {
}
}
}
- createOptionalityExpression(iu, optionalAbstractRequirements);
}
private void expandLifeCycle(IInstallableUnit iu, boolean isRootIu) throws ContradictionException {
@@ -797,8 +816,6 @@ public class Projector {
createNegation(iu, req);
}
- private boolean emptyBecauseFiltered;
-
/**
* @param req
* @return a list of mandatory requirements if any, an empty list if req.isOptional().
@@ -828,7 +845,7 @@ public class Projector {
for (int i = 0; i < changes.size(); i++) {
IRequirementChange change = changes.get(i);
for (int j = 0; j < originalRequirements.length; j++) {
- if (originalRequirements[j] != null && change.matches((IRequiredCapability) originalRequirements[j])) {
+ if (originalRequirements[j] != null && safeMatch(originalRequirements, change, j)) {
found = true;
if (change.newValue() != null)
rrr.add(new IRequirement[] {originalRequirements[j], change.newValue()});
@@ -850,24 +867,12 @@ public class Projector {
return rrr.toArray(new IRequirement[rrr.size()][]);
}
- /**
- * Optional requirements are encoded via:
- * ABS -> (match1(req) or match2(req) or ... or matchN(req))
- * noop(IU)-> ~ABS
- * IU -> (noop(IU) or ABS)
- * @param iu
- * @param optionalRequirements
- * @throws ContradictionException
- */
- private void createOptionalityExpression(IInstallableUnit iu, List<AbstractVariable> optionalRequirements) throws ContradictionException {
- if (optionalRequirements.isEmpty())
- return;
- AbstractVariable noop = getNoOperationVariable(iu);
- for (AbstractVariable abs : optionalRequirements) {
- createIncompatibleValues(abs, noop);
+ private boolean safeMatch(IRequirement[] originalRequirements, IRequirementChange change, int j) {
+ try {
+ return change.matches((IRequiredCapability) originalRequirements[j]);
+ } catch (ClassCastException e) {
+ return false;
}
- optionalRequirements.add(noop);
- createImplication(iu, optionalRequirements, Explanation.OPTIONAL_REQUIREMENT);
}
//This will create as many implication as there is element in the right argument
@@ -948,18 +953,6 @@ public class Projector {
dependencyHelper.atMost(1, (Object[]) ius).named(new Explanation.Singleton(ius));
}
- private void createIncompatibleValues(AbstractVariable v1, AbstractVariable v2) throws ContradictionException {
- AbstractVariable[] vars = {v1, v2};
- if (DEBUG) {
- StringBuffer b = new StringBuffer();
- for (int i = 0; i < vars.length; i++) {
- b.append(vars[i].toString());
- }
- Tracing.debug("At most 1 of " + b); //$NON-NLS-1$
- }
- dependencyHelper.atMost(1, (Object[]) vars).named(Explanation.OPTIONAL_REQUIREMENT);
- }
-
private AbstractVariable getAbstractVariable(IRequirement req) {
return getAbstractVariable(req, true);
}
@@ -972,15 +965,6 @@ public class Projector {
return abstractVariable;
}
- private AbstractVariable getNoOperationVariable(IInstallableUnit iu) {
- AbstractVariable v = noopVariables.get(iu);
- if (v == null) {
- v = DEBUG_ENCODING ? new AbstractVariable("Noop_" + iu.toString()) : new AbstractVariable(); //$NON-NLS-1$
- noopVariables.put(iu, v);
- }
- return v;
- }
-
private AbstractVariable getNonGreedyVariable(IInstallableUnit iu) {
AbstractVariable v = nonGreedyVariables.get(iu);
if (v == null) {
@@ -1007,7 +991,7 @@ public class Projector {
backToIU();
long stop = System.currentTimeMillis();
if (DEBUG)
- Tracing.debug("Solver solution found: " + (stop - start)); //$NON-NLS-1$
+ Tracing.debug("Solver solution found in: " + (stop - start) + " ms."); //$NON-NLS-1$
} else {
long stop = System.currentTimeMillis();
if (DEBUG) {
@@ -1029,6 +1013,7 @@ public class Projector {
private void backToIU() {
solution = new ArrayList<IInstallableUnit>();
+ //TODO WORK AROUND BECAUE OF A BUG IN SAT4J
IVec<Object> sat4jSolution = dependencyHelper.getSolution();
for (Iterator<Object> iter = sat4jSolution.iterator(); iter.hasNext();) {
Object var = iter.next();
@@ -1111,4 +1096,8 @@ public class Projector {
}
existingMatches.retainAll(matches);
}
+
+ public void setUserDefined(boolean containsKey) {
+ userDefinedFunction = containsKey;
+ }
} \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/SimplePlanner.java b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/SimplePlanner.java
index f733b27..7c57293 100644
--- a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/SimplePlanner.java
+++ b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/SimplePlanner.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2010 IBM Corporation and others. All rights reserved. This
+ * Copyright (c) 2007, 2013 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
@@ -8,6 +8,7 @@
* IBM Corporation - initial API and implementation
* Genuitec - bug fixes
* Sonatype, Inc. - ongoing development
+ * Red Hat, Inc. - support for remediation page
******************************************************************************/
package org.eclipse.equinox.internal.p2.director;
@@ -152,16 +153,20 @@ public class SimplePlanner implements IPlanner {
MultiStatus root = new MultiStatus(DirectorActivator.PI_DIRECTOR, 1, Messages.Director_Unsatisfied_Dependencies, null);
//try to find a more specific root message if possible
String specificMessage = null;
+ int errorCode = 0;
for (Explanation next : explanations) {
root.add(next.toStatus());
- if (specificMessage == null && next instanceof Explanation.MissingIU)
+ if (specificMessage == null && next instanceof Explanation.MissingIU) {
specificMessage = Messages.Explanation_rootMissing;
- else if (specificMessage == null && next instanceof Explanation.Singleton)
+ errorCode = 10053;
+ } else if (specificMessage == null && next instanceof Explanation.Singleton) {
specificMessage = Messages.Explanation_rootSingleton;
+ errorCode = 10054;
+ }
}
//use a more specific root message if available
if (specificMessage != null) {
- MultiStatus newRoot = new MultiStatus(DirectorActivator.PI_DIRECTOR, 1, specificMessage, null);
+ MultiStatus newRoot = new MultiStatus(DirectorActivator.PI_DIRECTOR, errorCode, specificMessage, null);
newRoot.merge(root);
root = newRoot;
}
@@ -333,6 +338,7 @@ public class SimplePlanner implements IPlanner {
final IQueryable<IInstallableUnit>[] queryables = new IQueryable[] {slice, new QueryableArray(profileChangeRequest.getAdditions().toArray(new IInstallableUnit[profileChangeRequest.getAdditions().size()]))};
slice = new CompoundQueryable<IInstallableUnit>(queryables);
Projector projector = new Projector(slice, newSelectionContext, slicer.getNonGreedyIUs(), satisfyMetaRequirements(profileChangeRequest.getProfileProperties()));
+ projector.setUserDefined(profileChangeRequest.getPropertiesToAdd().containsKey("_internal_user_defined_"));
projector.encode((IInstallableUnit) updatedPlan[0], (IInstallableUnit[]) updatedPlan[1], profile, profileChangeRequest.getAdditions(), sub.newChild(ExpandWork / 4));
IStatus s = projector.invokeSolver(sub.newChild(ExpandWork / 4));
if (s.getSeverity() == IStatus.CANCEL) {
@@ -747,7 +753,8 @@ public class SimplePlanner implements IPlanner {
//Now add any other requirement that we need to see satisfied
if (profileChangeRequest.getExtraRequirements() != null)
gatheredRequirements.addAll(profileChangeRequest.getExtraRequirements());
- return new Object[] {createIURepresentingTheProfile(gatheredRequirements), alreadyInstalled.toArray(IInstallableUnit.class)};
+ IInstallableUnit[] existingRoots = profileChangeRequest.getProfile().query(new IUProfilePropertyQuery(INCLUSION_RULES, IUProfilePropertyQuery.ANY), null).toArray(IInstallableUnit.class);
+ return new Object[] {createIURepresentingTheProfile(gatheredRequirements), existingRoots};
}
private IRequirement createRequirement(IInstallableUnit iu, String rule) {
diff --git a/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/UserDefinedOptimizationFunction.java b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/UserDefinedOptimizationFunction.java
new file mode 100644
index 0000000..6a8d69c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.director/src/org/eclipse/equinox/internal/p2/director/UserDefinedOptimizationFunction.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2013 Daniel Le Berre 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:
+ * Daniel Le Berre - initial API and implementation
+ * Red Hat, Inc. - support for remediation page
+ ******************************************************************************/
+package org.eclipse.equinox.internal.p2.director;
+
+import java.math.BigInteger;
+import java.util.*;
+import org.eclipse.equinox.internal.p2.director.Projector.AbstractVariable;
+import org.eclipse.equinox.p2.metadata.*;
+import org.eclipse.equinox.p2.query.*;
+import org.sat4j.pb.tools.*;
+import org.sat4j.specs.ContradictionException;
+
+public class UserDefinedOptimizationFunction extends OptimizationFunction {
+ private Collection<IInstallableUnit> alreadyExistingRoots;
+ private LexicoHelper<Object, Explanation> dependencyHelper;
+ private IQueryable<IInstallableUnit> picker;
+ private List changeVariables = new ArrayList();
+ private List removalVariables = new ArrayList();
+ private List newVariables = new ArrayList();
+
+ public UserDefinedOptimizationFunction(IQueryable<IInstallableUnit> lastState, List<AbstractVariable> abstractVariables, List<AbstractVariable> optionalVariables, IQueryable<IInstallableUnit> picker, IInstallableUnit selectionContext, Map<String, Map<Version, IInstallableUnit>> slice, DependencyHelper<Object, Explanation> dependencyHelper, Collection<IInstallableUnit> alreadyInstalledIUs) {
+ super(lastState, abstractVariables, optionalVariables, picker, selectionContext, slice);
+ this.picker = picker;
+ this.slice = slice;
+ this.dependencyHelper = (LexicoHelper<Object, Explanation>) dependencyHelper;
+ this.alreadyExistingRoots = alreadyInstalledIUs;
+ }
+
+ public List<WeightedObject<? extends Object>> createOptimizationFunction(IInstallableUnit metaIu, Collection<IInstallableUnit> newRoots) {
+ List weightedObjects = new ArrayList();
+ List objects = new ArrayList();
+ BigInteger weight = BigInteger.valueOf(slice.size() + 1);
+ String[] criteria = new String[] {"+new", "-removed", "-changed"};
+ BigInteger currentWeight = weight.pow(criteria.length - 1);
+ int formermaxvarid = dependencyHelper.getSolver().nextFreeVarId(false);
+ int newmaxvarid;
+ boolean maximizes;
+ Object thing;
+ for (int i = 0; i < criteria.length; i++) {
+ if (criteria[i].endsWith("new")) {
+ weightedObjects.clear();
+ newRoots(weightedObjects, criteria[i].startsWith("+") ? currentWeight.negate() : currentWeight, metaIu);
+ currentWeight = currentWeight.divide(weight);
+ } else if (criteria[i].endsWith("removed")) {
+ weightedObjects.clear();
+ removedRoots(weightedObjects, criteria[i].startsWith("+") ? currentWeight.negate() : currentWeight, metaIu);
+ currentWeight = currentWeight.divide(weight);
+ // } else if (criteria[i].endsWith("notuptodate")) {
+ // weightedObjects.clear();
+ // notuptodate(weightedObjects, criteria[i].startsWith("+") ? currentWeight.negate() : currentWeight, metaIu);
+ // currentWeight = currentWeight.divide(weight);
+ // } else if (criteria[i].endsWith("unsat_recommends")) {
+ // weightedObjects.clear();
+ // optional(weightedObjects, criteria[i].startsWith("+") ? currentWeight.negate() : currentWeight, metaIu);
+ // currentWeight = currentWeight.divide(weight);
+ // } else if (criteria[i].endsWith("versionchanged")) {
+ // weightedObjects.clear();
+ // versionChanged(weightedObjects, criteria[i].startsWith("+") ? currentWeight.negate() : currentWeight, metaIu);
+ } else if (criteria[i].endsWith("changed")) {
+ weightedObjects.clear();
+ changedRoots(weightedObjects, criteria[i].startsWith("+") ? currentWeight.negate() : currentWeight, metaIu);
+ currentWeight = currentWeight.divide(weight);
+ // } else if (criteria[i].contains("sum")) {
+ // weightedObjects.clear();
+ // sum(weightedObjects, criteria[i].charAt(0) == '-', metaIu, Options.extractSumProperty(criteria[i]));
+ // dependencyHelper.addWeightedCriterion(weightedObjects);
+ // System.out.println("# criteria " + criteria[i].substring(1) + " size is " + weightedObjects.size());
+ // continue;
+ // } else {
+ // System.out.println("Skipping unknown criteria:" + criteria[i]);
+ }
+ objects.clear();
+ maximizes = criteria[i].startsWith("+");
+ for (Iterator it = weightedObjects.iterator(); it.hasNext();) {
+ thing = ((WeightedObject) it.next()).thing;
+ if (maximizes) {
+ thing = dependencyHelper.not(thing);
+ }
+ objects.add(thing);
+ }
+ dependencyHelper.addCriterion(objects);
+ newmaxvarid = dependencyHelper.getSolver().nextFreeVarId(false);
+ // System.out.println("# criteria " + criteria[i].substring(1) + " size is " + objects.size() + " using new vars " + formermaxvarid + " to " + newmaxvarid);
+ formermaxvarid = newmaxvarid;
+ }
+ weightedObjects.clear();
+ return null;
+ }
+
+ protected void changedRoots(List<WeightedObject<?>> weightedObjects, BigInteger weight, IInstallableUnit entryPointIU) {
+ Collection<IRequirement> requirements = entryPointIU.getRequirements();
+ for (IRequirement req : requirements) {
+ IQuery<IInstallableUnit> query = QueryUtil.createMatchQuery(req.getMatches());
+ IQueryResult<IInstallableUnit> matches = picker.query(query, null);
+ Object[] changed = new Object[matches.toUnmodifiableSet().size()];
+ int i = 0;
+ for (IInstallableUnit match : matches) {
+ changed[i++] = isInstalledAsRoot(match) ? dependencyHelper.not(match) : match;
+ }
+ try {
+ Projector.AbstractVariable abs = new Projector.AbstractVariable("CHANGED"); //TODO
+ changeVariables.add(abs);
+ // abs <=> iuv1 or not iuv2 or ... or not iuvn
+ dependencyHelper.or(FakeExplanation.getInstance(), abs, changed);
+ weightedObjects.add(WeightedObject.newWO(abs, weight));
+ } catch (ContradictionException e) {
+ // TODO Auto-generated catch block TODO
+ e.printStackTrace();
+ }
+ }
+ }
+
+ protected void newRoots(List<WeightedObject<?>> weightedObjects, BigInteger weight, IInstallableUnit entryPointIU) {
+ Collection<IRequirement> requirements = entryPointIU.getRequirements();
+ for (IRequirement req : requirements) {
+ IQuery<IInstallableUnit> query = QueryUtil.createMatchQuery(req.getMatches());
+ IQueryResult<IInstallableUnit> matches = picker.query(query, null);
+ boolean oneInstalled = false;
+ for (IInstallableUnit match : matches) {
+ oneInstalled = oneInstalled || isInstalledAsRoot(match);
+ }
+ if (!oneInstalled) {
+ try {
+ Projector.AbstractVariable abs = new Projector.AbstractVariable("NEW"); //TODO
+ newVariables.add(abs);
+ // a <=> iuv1 or ... or iuvn
+ dependencyHelper.or(FakeExplanation.getInstance(), abs, matches.toArray(IInstallableUnit.class));
+ weightedObjects.add(WeightedObject.newWO(abs, weight));
+ } catch (ContradictionException e) {
+ // should not happen
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ protected void removedRoots(List<WeightedObject<?>> weightedObjects, BigInteger weight, IInstallableUnit entryPointIU) {
+ Collection<IRequirement> requirements = entryPointIU.getRequirements();
+ for (IRequirement req : requirements) {
+ IQuery<IInstallableUnit> query = QueryUtil.createMatchQuery(req.getMatches());
+ IQueryResult<IInstallableUnit> matches = picker.query(query, null);
+ boolean installed = false;
+ Object[] literals = new Object[matches.toUnmodifiableSet().size()];
+ int i = 0;
+ for (IInstallableUnit match : matches) {
+ installed = installed || isInstalledAsRoot(match);
+ literals[i++] = dependencyHelper.not(match);
+ }
+ if (installed) {
+ try {
+ Projector.AbstractVariable abs = new Projector.AbstractVariable("REMOVED"); //TODO
+ removalVariables.add(abs);
+ // abs <=> not iuv1 and ... and not iuvn
+ dependencyHelper.and(FakeExplanation.getInstance(), abs, literals);
+ weightedObjects.add(WeightedObject.newWO(abs, weight));
+ } catch (ContradictionException e) {
+ // should not happen TODO
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ private static class FakeExplanation extends Explanation {
+ private static Explanation singleton = new FakeExplanation();
+
+ public static Explanation getInstance() {
+ return singleton;
+ }
+
+ protected int orderValue() {
+ return Explanation.OTHER_REASON;
+ }
+
+ @Override
+ public int shortAnswer() {
+ return 0;
+ }
+
+ }
+
+ private boolean isInstalledAsRoot(IInstallableUnit isInstalled) {
+ for (IInstallableUnit installed : alreadyExistingRoots) {
+ if (isInstalled.equals(installed))
+ return true;
+ }
+ return false;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/IQueryResult.java b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/IQueryResult.java
index 82f3363..acdbc5e 100644
--- a/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/IQueryResult.java
+++ b/bundles/org.eclipse.equinox.p2.metadata/src/org/eclipse/equinox/p2/query/IQueryResult.java
@@ -17,7 +17,7 @@ import java.util.Set;
*
* @since 2.0
*/
-public interface IQueryResult<T> extends IQueryable<T> {
+public interface IQueryResult<T> extends IQueryable<T>, Iterable<T> {
/**
* Returns whether this QueryResult is empty.
* @return <code>true</code> if this QueryResult has accepted any results,
diff --git a/bundles/org.eclipse.equinox.p2.operations/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.operations/META-INF/MANIFEST.MF
index cf4c946..a585e42 100644
--- a/bundles/org.eclipse.equinox.p2.operations/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.operations/META-INF/MANIFEST.MF
@@ -25,6 +25,7 @@ Import-Package: org.eclipse.equinox.internal.p2.core.helpers,
org.eclipse.equinox.p2.engine;version="[2.0.0,3.0.0)",
org.eclipse.equinox.p2.engine.query;version="[2.0.0,3.0.0)",
org.eclipse.equinox.p2.metadata;version="[2.0.0,3.0.0)",
+ org.eclipse.equinox.p2.metadata.expression;version="2.0.0",
org.eclipse.equinox.p2.planner;version="[2.0.0,3.0.0)",
org.eclipse.equinox.p2.query;version="[2.0.0,3.0.0)",
org.eclipse.equinox.p2.repository;version="[2.0.0,3.0.0)",
diff --git a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/IStatusCodes.java b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/IStatusCodes.java
index 61bdb13..580cdf4 100644
--- a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/IStatusCodes.java
+++ b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/IStatusCodes.java
@@ -45,6 +45,7 @@ public interface IStatusCodes {
public static final int UNEXPECTED_NOTHING_TO_DO = 10050;
public static final int EXPECTED_NOTHING_TO_DO = 10051;
public static final int OPERATION_ALREADY_IN_PROGRESS = 10052;
+ public static final int MISSING_REQUIREMENTS = 10053;
// Status codes associated with repositories
public static final int INVALID_REPOSITORY_LOCATION = 10100;
diff --git a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/Messages.java b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/Messages.java
index 9180113..792778b 100644
--- a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/Messages.java
+++ b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/Messages.java
@@ -66,8 +66,9 @@ public class Messages extends NLS {
public static String UpdateOperation_ResolveJobName;
public static String UpdateOperation_UpdateJobName;
- public static String RelaxedUpdateOperation_ResolveJobName;
- public static String RelaxedUpdateOperation_UpdateJobName;
+ public static String RemediationOperation_ProfileChangeRequestProgress;
+ public static String RemediationOperation_ResolveJobName;
+ public static String RemediationOperation_RemediationJobName;
public static String OperationFactory_noAgent;
public static String OperationFactory_noIUFound;
diff --git a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/PlanAnalyzer.java b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/PlanAnalyzer.java
index f32511f..552e462 100644
--- a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/PlanAnalyzer.java
+++ b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/PlanAnalyzer.java
@@ -129,6 +129,15 @@ public class PlanAnalyzer {
report.addSummaryStatus(fail);
}
}
+ } else {
+ if (plannerStatus.getCode() == IStatusCodes.MISSING_REQUIREMENTS) {
+ IStatus existingSummaryStatus = report.getSummaryStatus();
+ MultiStatus newSummaryStatus = new MultiStatus(Activator.ID, IStatusCodes.MISSING_REQUIREMENTS, Messages.ResolutionResult_SummaryStatus, null);
+ if (!existingSummaryStatus.isOK()) {
+ newSummaryStatus.addAll(existingSummaryStatus);
+ report.setSummaryStatus(newSummaryStatus);
+ }
+ }
}
// Now process the side effects
diff --git a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/RequestFlexer.java b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/RequestFlexer.java
new file mode 100644
index 0000000..94ff050
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/RequestFlexer.java
@@ -0,0 +1,344 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, 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:
+ * Red Hat, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.operations;
+
+import java.util.*;
+import java.util.Map.Entry;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
+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.metadata.expression.ExpressionUtil;
+import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
+import org.eclipse.equinox.p2.planner.IPlanner;
+import org.eclipse.equinox.p2.planner.IProfileChangeRequest;
+import org.eclipse.equinox.p2.query.*;
+
+public class RequestFlexer {
+ 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$
+
+ IPlanner planner;
+
+ private boolean allowInstalledUpdate = false;
+ private boolean allowInstalledRemoval = false;
+ private boolean allowDifferentVersion = false;
+ private boolean allowPartialInstall = false;
+ private ProvisioningContext provisioningContext;
+
+ Set<IRequirement> requirementsForElementsBeingInstalled = new HashSet<IRequirement>();
+ Set<IRequirement> requirementsForElementsAlreadyInstalled = new HashSet<IRequirement>();
+ Map<IRequirement, Map> propertiesPerRequirement = new HashMap();
+ Map<IRequirement, List<String>> removedPropertiesPerRequirement = new HashMap();
+
+ IProfile profile;
+
+ private boolean foundDifferentVersionsForElementsToInstall = false;
+ private boolean foundDifferentVersionsForElementsInstalled = false;
+ private Set<IInstallableUnit> futureOptionalIUs;
+
+ public RequestFlexer(IPlanner planner) {
+ this.planner = planner;
+ }
+
+ public void setAllowInstalledElementChange(boolean allow) {
+ allowInstalledUpdate = allow;
+ }
+
+ public void setAllowInstalledElementRemoval(boolean allow) {
+ allowInstalledRemoval = allow;
+ }
+
+ public void setAllowDifferentVersion(boolean allow) {
+ allowDifferentVersion = allow;
+ }
+
+ public void setAllowPartialInstall(boolean allow) {
+ allowPartialInstall = allow;
+ }
+
+ public void setProvisioningContext(ProvisioningContext context) {
+ provisioningContext = context;
+ }
+
+ public IProfileChangeRequest getChangeRequest(IProfileChangeRequest request, IProfile prof, IProgressMonitor monitor) {
+ this.profile = prof;
+ IProfileChangeRequest loosenedRequest = computeLooseRequest(request);
+ if (canShortCircuit(request)) {
+ return null;
+ }
+ IProvisioningPlan intermediaryPlan = resolve(loosenedRequest);
+ if (!intermediaryPlan.getStatus().isOK())
+ return null;
+ if (intermediaryPlan.getAdditions().query(QueryUtil.ALL_UNITS, new NullProgressMonitor()).isEmpty() && intermediaryPlan.getRemovals().query(QueryUtil.ALL_UNITS, new NullProgressMonitor()).isEmpty())
+ //No changes, we can't return anything
+ return null;
+ IProfileChangeRequest effectiveRequest = computeEffectiveChangeRequest(intermediaryPlan, loosenedRequest, request);
+ if (effectiveRequest.getAdditions().isEmpty() && effectiveRequest.getRemovals().isEmpty())
+ return null;
+ return effectiveRequest;
+ }
+
+ private boolean canShortCircuit(IProfileChangeRequest originalRequest) {
+ //Case where the user is asking to install only some of the requested IUs but there is only one IU to install.
+ if (allowPartialInstall)
+ if (originalRequest.getAdditions().size() == 1 && originalRequest.getRemovals().isEmpty())
+ return true;
+
+ //When we can find a different version of the IU but the only version available is the one the user is asking to install
+ if (allowDifferentVersion && !allowPartialInstall && !allowInstalledRemoval && !allowInstalledUpdate)
+ if (!foundDifferentVersionsForElementsToInstall)
+ return true;
+
+ if (allowInstalledUpdate && !allowDifferentVersion && !allowPartialInstall && !allowInstalledRemoval)
+ if (!foundDifferentVersionsForElementsInstalled)
+ return true;
+
+ return false;
+ }
+
+ //From the loosened request and the plan resulting from its resolution, create a new profile change request representing the delta between where the profile currently is
+ // and the plan returned.
+ //To perform this efficiently, this relies on a traversal of the requirements that are part of the loosened request.
+ private IProfileChangeRequest computeEffectiveChangeRequest(IProvisioningPlan intermediaryPlan, IProfileChangeRequest loosenedRequest, IProfileChangeRequest originalRequest) {
+ IProfileChangeRequest finalChangeRequest = planner.createChangeRequest(profile);
+
+ for (IRequirement beingInstalled : requirementsForElementsBeingInstalled) {
+ IQuery<IInstallableUnit> query = QueryUtil.createMatchQuery(beingInstalled.getMatches());
+ IQueryResult<IInstallableUnit> matches = intermediaryPlan.getFutureState().query(QueryUtil.createLatestQuery(query), null);
+ IInstallableUnit replacementIU = null;
+ if (!matches.isEmpty()) {
+ replacementIU = matches.iterator().next();
+ finalChangeRequest.add(replacementIU);
+ adaptIUPropertiesToNewIU(beingInstalled, replacementIU, finalChangeRequest);
+ }
+ }
+
+ for (IRequirement alreadyInstalled : requirementsForElementsAlreadyInstalled) {
+ IQuery<IInstallableUnit> query = QueryUtil.createMatchQuery(alreadyInstalled.getMatches());
+ IQueryResult<IInstallableUnit> matches = intermediaryPlan.getFutureState().query(QueryUtil.createLatestQuery(query), null);
+ IInstallableUnit potentialRootChange = null;
+ if (!matches.isEmpty())
+ potentialRootChange = matches.iterator().next();
+
+ IQueryResult<IInstallableUnit> iuAlreadyInstalled = profile.available(query, new NullProgressMonitor());
+
+ if (!iuAlreadyInstalled.isEmpty()) {//This deals with the case where the root has not changed
+ if (potentialRootChange != null && iuAlreadyInstalled.toUnmodifiableSet().contains(potentialRootChange))
+ continue;
+ }
+ finalChangeRequest.removeAll(iuAlreadyInstalled.toUnmodifiableSet());
+ if (potentialRootChange != null) {
+ if (!finalChangeRequest.getAdditions().contains(potentialRootChange)) {//So we don't add the same IU twice for addition
+ finalChangeRequest.add(potentialRootChange);
+ adaptIUPropertiesToNewIU(alreadyInstalled, potentialRootChange, finalChangeRequest);
+ }
+ }
+ }
+
+ finalChangeRequest.removeAll(originalRequest.getRemovals());
+ if (originalRequest.getExtraRequirements() != null)
+ finalChangeRequest.addExtraRequirements(originalRequest.getExtraRequirements());
+ return finalChangeRequest;
+ }
+
+ private void adaptIUPropertiesToNewIU(IRequirement beingInstalled, IInstallableUnit newIU, IProfileChangeRequest finalChangeRequest) {
+ Map<String, String> associatedProperties = propertiesPerRequirement.get(beingInstalled);
+ if (associatedProperties != null) {
+ Set<Entry<String, String>> entries = associatedProperties.entrySet();
+ for (Entry<String, String> entry : entries) {
+ finalChangeRequest.setInstallableUnitProfileProperty(newIU, entry.getKey(), entry.getValue());
+ }
+ }
+ List<String> removedProperties = removedPropertiesPerRequirement.get(beingInstalled);
+ if (removedProperties != null) {
+ for (String toRemove : removedProperties) {
+ finalChangeRequest.removeInstallableUnitProfileProperty(newIU, toRemove);
+ }
+ }
+ }
+
+ //Create a request where the original requirements are "loosened" according to flags specified in this instance
+ //The resulting profile change request uses the requirements specified using p2QL and those appear in the extraRequirements.
+ private IProfileChangeRequest computeLooseRequest(IProfileChangeRequest originalRequest) {
+ IProfileChangeRequest loosenedRequest = planner.createChangeRequest(profile);
+ loosenUpOriginalRequest(loosenedRequest, originalRequest);
+ loosenUpInstalledSoftware(loosenedRequest, originalRequest);
+ return loosenedRequest;
+ }
+
+ private boolean removalRequested(IInstallableUnit removalRequested, IProfileChangeRequest request) {
+ return request.getRemovals().contains(removalRequested);
+ }
+
+ private IProvisioningPlan resolve(IProfileChangeRequest temporaryRequest) {
+ temporaryRequest.setProfileProperty("_internal_user_defined_", "true");
+ return planner.getProvisioningPlan(temporaryRequest, provisioningContext, null);
+ }
+
+ //Loosen the request originally emitted.
+ //For example if the user said "install A 1.0", then a new Requirement is added saying (install A 1.0 or install A 2.0), this depending on the configuration flags
+ private void loosenUpOriginalRequest(IProfileChangeRequest newRequest, IProfileChangeRequest originalRequest) {
+ //First deal with the IUs that are being added
+ Collection<IInstallableUnit> requestedAdditions = originalRequest.getAdditions();
+ for (IInstallableUnit addedIU : requestedAdditions) {
+ Collection<IInstallableUnit> potentialUpdates = allowDifferentVersion ? findAllVersionsAvailable(addedIU) : new ArrayList();
+ foundDifferentVersionsForElementsToInstall = (foundDifferentVersionsForElementsToInstall || (potentialUpdates.size() == 0 ? false : true));
+ potentialUpdates.add(addedIU); //Make sure that we include the IU that we were initially trying to install
+
+ Collection<IRequirement> newRequirement = new ArrayList<IRequirement>(1);
+ IRequirement req = createORRequirement(potentialUpdates, allowPartialInstall || isRequestedInstallationOptional(addedIU, originalRequest));
+ newRequirement.add(req);
+ newRequest.addExtraRequirements(newRequirement);
+ requirementsForElementsBeingInstalled.addAll(newRequirement);
+ rememberIUProfileProperties(addedIU, req, originalRequest, false);
+ }
+
+ //Deal with the IUs requested for removal
+ newRequest.removeAll(originalRequest.getRemovals());
+
+ //Deal with extra requirements that could have been specified
+ if (originalRequest.getExtraRequirements() != null)
+ newRequest.addExtraRequirements(originalRequest.getExtraRequirements());
+ }
+
+ //This keeps track for each requirement created (those created to loosen the constraint), of the original IU and the properties associated with it in the profile
+ //This is used for more easily construct the final profile change request
+ private void rememberIUProfileProperties(IInstallableUnit iu, IRequirement req, IProfileChangeRequest originalRequest, boolean includeProfile) {
+ Map<String, String> allProperties = new HashMap<String, String>();
+ if (includeProfile) {
+ Map<String, String> tmp = new HashMap(profile.getInstallableUnitProperties(iu));
+ List<String> propertiesToRemove = ((ProfileChangeRequest) originalRequest).getInstallableUnitProfilePropertiesToRemove().get(iu);
+ if (propertiesToRemove != null) {
+ for (String toRemove : propertiesToRemove) {
+ tmp.remove(toRemove);
+ }
+ }
+ allProperties.putAll(tmp);
+ }
+
+ Map<String, String> propertiesInRequest = ((ProfileChangeRequest) originalRequest).getInstallableUnitProfilePropertiesToAdd().get(iu);
+ if (propertiesInRequest != null)
+ allProperties.putAll(propertiesInRequest);
+
+ propertiesPerRequirement.put(req, allProperties);
+
+ List<String> removalInRequest = ((ProfileChangeRequest) originalRequest).getInstallableUnitProfilePropertiesToRemove().get(iu);
+ if (removalInRequest != null)
+ removedPropertiesPerRequirement.put(req, removalInRequest);
+ }
+
+ private boolean isRequestedInstallationOptional(IInstallableUnit iu, IProfileChangeRequest originalRequest) {
+ Map<String, String> match = ((ProfileChangeRequest) originalRequest).getInstallableUnitProfilePropertiesToAdd().get(iu);
+ if (match == null)
+ return false;
+ return INCLUSION_OPTIONAL.equals(match.get(INCLUSION_RULES));
+ }
+
+ private Collection<IInstallableUnit> findAllVersionsAvailable(IInstallableUnit iu) {
+ Collection<IInstallableUnit> allVersions = new HashSet();
+ allVersions.addAll(findIUsWithSameId(iu));
+ allVersions.addAll(findUpdates(iu));
+ return allVersions;
+ }
+
+ private Collection<IInstallableUnit> findIUsWithSameId(IInstallableUnit iu) {
+ return provisioningContext.getMetadata(null).query(QueryUtil.createIUQuery(iu.getId()), null).toUnmodifiableSet();
+ }
+
+ private Collection<IInstallableUnit> findUpdates(IInstallableUnit iu) {
+ Collection<IInstallableUnit> availableUpdates = new HashSet<IInstallableUnit>();
+ IQueryResult<IInstallableUnit> updatesAvailable = planner.updatesFor(iu, provisioningContext, null);
+ for (Iterator<IInstallableUnit> iterator = updatesAvailable.iterator(); iterator.hasNext();) {
+ availableUpdates.add(iterator.next());
+ }
+ return availableUpdates;
+ }
+
+ //Create an OR expression that is matching all the entries from the given collection
+ private IRequirement createORRequirement(Collection<IInstallableUnit> findUpdates, boolean optional) {
+ StringBuffer expression = new StringBuffer();
+ Object[] expressionParameters = new Object[findUpdates.size() * 2];
+ int count = 0;
+ for (IInstallableUnit iu : findUpdates) {
+ expression.append("(id == $").append(count * 2).append(" && version == $").append(count * 2 + 1).append(')'); //$NON-NLS-1$//$NON-NLS-2$
+ if (findUpdates.size() > 1 && count < findUpdates.size() - 1)
+ expression.append(" || "); //$NON-NLS-1$
+ expressionParameters[count * 2] = iu.getId();
+ expressionParameters[count * 2 + 1] = iu.getVersion();
+ count++;
+ }
+ IMatchExpression<IInstallableUnit> iuMatcher = ExpressionUtil.getFactory().<IInstallableUnit> matchExpression(ExpressionUtil.parse(expression.toString()), expressionParameters);
+ return MetadataFactory.createRequirement(iuMatcher, null, optional ? 0 : 1, 1, true);
+ }
+
+ //Loosen up the IUs that are already part of the profile
+ //Given how we are creating our request, this needs to take into account the removal from the original request as well as the change in inclusion
+ private IProfileChangeRequest loosenUpInstalledSoftware(IProfileChangeRequest request, IProfileChangeRequest originalRequest) {
+ IQueryResult<IInstallableUnit> allRoots = profile.query(new IUProfilePropertyQuery(INCLUSION_RULES, IUProfilePropertyQuery.ANY), null);
+
+ for (IInstallableUnit existingIU : allRoots) {
+ Collection<IInstallableUnit> potentialUpdates = allowInstalledUpdate ? findUpdates(existingIU) : new HashSet();
+ foundDifferentVersionsForElementsInstalled = (foundDifferentVersionsForElementsInstalled || (potentialUpdates.size() == 0 ? false : true));
+ potentialUpdates.add(existingIU);
+ Collection<IRequirement> newRequirement = new ArrayList<IRequirement>(1);
+ //when the element is requested for removal or is installed optionally we make sure to mark it optional, otherwise the removal woudl fail
+ IRequirement req = createORRequirement(potentialUpdates, allowInstalledRemoval || removalRequested(existingIU, originalRequest) || isOptionallyInstalled(existingIU, originalRequest));
+ newRequirement.add(req);
+ request.addExtraRequirements(newRequirement);
+ requirementsForElementsAlreadyInstalled.addAll(newRequirement);
+ request.remove(existingIU);
+ rememberIUProfileProperties(existingIU, req, originalRequest, true);
+ }
+
+ return request;
+ }
+
+ //This return whether or not the given IU is installed optionally or not.
+ //This also take into account the future state
+ private boolean isOptionallyInstalled(IInstallableUnit existingIU, IProfileChangeRequest request) {
+ return computeFutureStateOfInclusion((ProfileChangeRequest) request).contains(existingIU);
+ }
+
+ //Given the change request, this returns the collection of optional IUs
+ private Set<IInstallableUnit> computeFutureStateOfInclusion(ProfileChangeRequest profileChangeRequest) {
+ if (futureOptionalIUs != null)
+ return futureOptionalIUs;
+
+ futureOptionalIUs = profileChangeRequest.getProfile().query(new IUProfilePropertyQuery(INCLUSION_RULES, INCLUSION_OPTIONAL), null).toSet();
+
+ Set<Entry<IInstallableUnit, List<String>>> propertiesBeingRemoved = profileChangeRequest.getInstallableUnitProfilePropertiesToRemove().entrySet();
+ for (Entry<IInstallableUnit, List<String>> propertyRemoved : propertiesBeingRemoved) {
+ if (propertyRemoved.getValue().contains(INCLUSION_RULES)) {
+ futureOptionalIUs.remove(propertyRemoved.getKey());
+ }
+ }
+
+ Set<Entry<IInstallableUnit, Map<String, String>>> propertiesBeingAdded = profileChangeRequest.getInstallableUnitProfilePropertiesToAdd().entrySet();
+ for (Entry<IInstallableUnit, Map<String, String>> propertyBeingAdded : propertiesBeingAdded) {
+ String inclusionRule = propertyBeingAdded.getValue().get(INCLUSION_RULES);
+ if (inclusionRule == null) {
+ continue;
+ }
+ if (INCLUSION_STRICT.equals(inclusionRule)) {
+ futureOptionalIUs.remove(propertyBeingAdded.getKey());
+ }
+ if (INCLUSION_OPTIONAL.equals(inclusionRule)) {
+ futureOptionalIUs.add(propertyBeingAdded.getKey());
+ }
+ }
+ return futureOptionalIUs;
+
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/ResolutionResult.java b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/ResolutionResult.java
index 20c1740..16d360c 100644
--- a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/ResolutionResult.java
+++ b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/ResolutionResult.java
@@ -33,6 +33,10 @@ public class ResolutionResult {
return Status.OK_STATUS;
}
+ public void setSummaryStatus(MultiStatus status) {
+ summaryStatus = status;
+ }
+
public void addSummaryStatus(IStatus status) {
if (summaryStatus == null) {
summaryStatus = new MultiStatus(Activator.ID, 0, Messages.ResolutionResult_SummaryStatus, null);
diff --git a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/messages.properties b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/messages.properties
index 2d2253e..0147c05 100644
--- a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/messages.properties
+++ b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/internal/p2/operations/messages.properties
@@ -11,6 +11,8 @@
InstallOperation_ComputeProfileChangeProgress=Checking the install request
InstallOperation_InstallJobName=Installing Software
InstallOperation_ResolveJobName=Computing install requirements
+RemediationOperation_InstallJobName=Installing Software
+RemediationOperation_ResolveJobName=Computing remediation requirements
ProfileChangeOperation_NoProfileChangeRequest=Could not interpret the installation request.
ProfileChangeOperation_ResolveTaskName=Analyzing the install operation
ProvisioningJob_GenericErrorStatusMessage=Error encountered while running {0}
@@ -42,8 +44,10 @@ UninstallOperation_ResolveJobName=Calculating Uninstall Validity
UpdateOperation_ProfileChangeRequestProgress=Computing update request
UpdateOperation_ResolveJobName=Computing Update Requirements
UpdateOperation_UpdateJobName=Updating Software
-RelaxedUpdateOperation_ResolveJobName=Computing Update Requirements
-RelaxedUpdateOperation_UpdateJobName=Updating Software
+RemediationOperation_ProvisioningJobName=Cannot complete the operation, searching alternate solutions
+RemediationOperation_ProfileChangeRequestProgress=Computing alternate solutions
+RemediationOperation_ResolveJobName=Cannot complete the operation, searching alternate solutions
+RemediationOperation_RemediationJobName=Installing Software
OperationFactory_noAgent=This installation has not been configured properly. No provisioning agent can be found.
diff --git a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/RelaxedUpdateInstallOperation.java b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/RelaxedUpdateInstallOperation.java
deleted file mode 100644
index 8605f0f..0000000
--- a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/RelaxedUpdateInstallOperation.java
+++ /dev/null
@@ -1,112 +0,0 @@
-package org.eclipse.equinox.p2.operations;
-
-import java.util.*;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.MultiStatus;
-import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
-import org.eclipse.equinox.internal.p2.metadata.query.UpdateQuery;
-import org.eclipse.equinox.internal.p2.operations.Messages;
-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.*;
-
-/**
- * An operation that updates IUs with relaxed p2 constraints
- *
- * @noinstantiate This class is not intended to be instantiated by clients.
- * @noreference
- * @since 2.2
- */
-public class RelaxedUpdateInstallOperation extends ProfileChangeOperation {
-
- public RelaxedUpdateInstallOperation(ProvisioningSession session) {
- super(session);
- }
-
- @Override
- protected void computeProfileChangeRequest(MultiStatus status, IProgressMonitor monitor) {
- IProfileRegistry profileRegistry = (IProfileRegistry) session.getProvisioningAgent().getService(IProfileRegistry.SERVICE_NAME);
- IPlanner plan = (IPlanner) session.getProvisioningAgent().getService(IPlanner.SERVICE_NAME);
- IProfile prof = 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;
- }
-
- //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));
- }
- }
- }
- request = (ProfileChangeRequest) finalChangeRequest;
- }
-
- @Override
- protected String getResolveJobName() {
- return Messages.RelaxedUpdateOperation_ResolveJobName;
- }
-
- @Override
- protected String getProvisioningJobName() {
- return Messages.RelaxedUpdateOperation_UpdateJobName;
- }
-
-} \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/RemediationOperation.java b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/RemediationOperation.java
new file mode 100644
index 0000000..db3d608
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/RemediationOperation.java
@@ -0,0 +1,218 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, 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:
+ * Red Hat, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.p2.operations;
+
+import java.util.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
+import org.eclipse.equinox.internal.p2.operations.Messages;
+import org.eclipse.equinox.internal.p2.operations.RequestFlexer;
+import org.eclipse.equinox.p2.engine.IProfile;
+import org.eclipse.equinox.p2.planner.IPlanner;
+import org.eclipse.equinox.p2.planner.IProfileChangeRequest;
+
+//TODO Javadoc
+public class RemediationOperation extends ProfileChangeOperation {
+
+ private static int ZERO_WEIGHT = 0;
+ private static int LOW_WEIGHT = 1;
+ private static int MEDIUM_WEIGHT = 2;
+ private static int HIGH_WEIGHT = 3;
+ private List<Remedy> remedies;
+ private Remedy bestSolutionChangingTheRequest;
+ private Remedy bestSolutionChangingWhatIsInstalled;
+ private Remedy userSelectedRemedy;
+ private IProfileChangeRequest originalRequest;
+ private boolean isCheckForUpdates;
+
+ public boolean isCheckForUpdates() {
+ return isCheckForUpdates;
+ }
+
+ public RemediationOperation(ProvisioningSession session, IProfileChangeRequest iProfileChangeRequest) {
+ this(session, iProfileChangeRequest, null);
+
+ }
+
+ public RemediationOperation(ProvisioningSession session, IProfileChangeRequest originalRequest, List<RemedyConfig> configuration) {
+ this(session, originalRequest, false);
+ }
+
+ public RemediationOperation(ProvisioningSession session, IProfileChangeRequest originalRequest, boolean isCheckForUpdates) {
+ super(session);
+ this.originalRequest = originalRequest;
+ remedies = new ArrayList<Remedy>();
+ this.isCheckForUpdates = isCheckForUpdates;
+ }
+
+ public Remedy bestSolutionChangingTheRequest() {
+ return bestSolutionChangingTheRequest;
+ }
+
+ public Remedy bestSolutionChangingWhatIsInstalled() {
+ return bestSolutionChangingWhatIsInstalled;
+ }
+
+ public List<Remedy> getRemedies() {
+ return remedies;
+ }
+
+ @Override
+ protected void computeProfileChangeRequest(MultiStatus status, IProgressMonitor monitor) {
+ if (userSelectedRemedy != null) {
+ request = userSelectedRemedy.getRequest();
+ return;
+ }
+
+ try {
+ if (isCheckForUpdates)
+ status.add(computeCheckForUpdates(monitor));
+ else
+ status.add(computeAllRemediations(monitor));
+ } catch (OperationCanceledException e) {
+ status.add(Status.CANCEL_STATUS);
+ }
+ if (!isCheckForUpdates)
+ determineBestSolutions();
+ }
+
+ private IStatus computeCheckForUpdates(IProgressMonitor monitor) {
+ RemedyConfig config = new RemedyConfig();
+ config.allowDifferentVersion = true;
+ config.allowInstalledRemoval = false;
+ config.allowInstalledUpdate = true;
+ config.allowPartialInstall = false;
+ Remedy remedy = computeRemedy(config, monitor);
+ if (remedy != null) {
+ remedies.add(remedy);
+ }
+ return Status.OK_STATUS;
+ }
+
+ private IStatus computeAllRemediations(IProgressMonitor monitor) {
+ RemedyConfig[] remedyConfigs = RemedyConfig.getAllRemdyConfigs();
+ SubMonitor sub = SubMonitor.convert(monitor, remedyConfigs.length);
+ sub.setTaskName("Looking for alternate solutions");
+ List<Remedy> tmpRemedies = new ArrayList<Remedy>(remedyConfigs.length);
+ try {
+ for (int i = 0; i < remedyConfigs.length; i++) {
+ sub.subTask(i + " out of " + remedyConfigs.length); //$NON-NLS-1$
+ if (sub.isCanceled())
+ return Status.CANCEL_STATUS;
+ Remedy remedy = computeRemedy(remedyConfigs[i], sub.newChild(1, SubMonitor.SUPPRESS_ALL_LABELS));
+ if (remedy != null) {
+ tmpRemedies.add(remedy);
+ }
+ }
+ } finally {
+ sub.done();
+ }
+ remedies = tmpRemedies;
+ return Status.OK_STATUS;
+ }
+
+ private void determineBestSolutions() {
+ int beingInstalledWeight = 0;
+ int installationWeight = 0;
+ for (Iterator<Remedy> iterator = remedies.iterator(); iterator.hasNext();) {
+ Remedy remedy = iterator.next();
+ if (remedy.getRequest() != null) {
+ if (remedy.getBeingInstalledRelaxedWeight() > beingInstalledWeight && remedy.getInstallationRelaxedWeight() == 0) {
+ bestSolutionChangingTheRequest = remedy;
+ beingInstalledWeight = remedy.getBeingInstalledRelaxedWeight();
+ continue;
+ }
+ if (remedy.getInstallationRelaxedWeight() > installationWeight && remedy.getBeingInstalledRelaxedWeight() == 0) {
+ bestSolutionChangingWhatIsInstalled = remedy;
+ installationWeight = remedy.getInstallationRelaxedWeight();
+ continue;
+ }
+ request = remedy.getRequest();
+ }
+ }
+ if (bestSolutionChangingTheRequest != null)
+ request = bestSolutionChangingTheRequest.getRequest();
+ else if (bestSolutionChangingWhatIsInstalled != null)
+ request = bestSolutionChangingWhatIsInstalled.getRequest();
+ }
+
+ private Remedy computeRemedy(RemedyConfig configuration, IProgressMonitor monitor) {
+ Remedy remedy = new Remedy();
+ remedy.setConfig(configuration);
+ IPlanner planner = session.getPlanner();
+ IProfile profile = session.getProfileRegistry().getProfile(profileId);
+ //request = (ProfileChangeRequest) originalRequest.clone();
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowDifferentVersion(configuration.allowDifferentVersion);
+ av.setAllowInstalledElementChange(configuration.allowInstalledUpdate);
+ av.setAllowInstalledElementRemoval(configuration.allowInstalledRemoval);
+ av.setAllowPartialInstall(configuration.allowPartialInstall);
+ av.setProvisioningContext(getProvisioningContext());
+ remedy.setRequest((ProfileChangeRequest) av.getChangeRequest(originalRequest, profile, monitor));
+ if (remedy.getRequest() == null)
+ return null;
+
+ if (configuration.allowInstalledUpdate && !configuration.allowInstalledRemoval) {
+ remedy.setInstallationRelaxedWeight(HIGH_WEIGHT);
+ } else if (!configuration.allowInstalledUpdate && configuration.allowInstalledRemoval) {
+ remedy.setInstallationRelaxedWeight(MEDIUM_WEIGHT);
+ } else if (configuration.allowInstalledUpdate && configuration.allowInstalledRemoval) {
+ remedy.setInstallationRelaxedWeight(LOW_WEIGHT);
+ } else
+ remedy.setInstallationRelaxedWeight(ZERO_WEIGHT);
+
+ if (configuration.allowDifferentVersion && !configuration.allowPartialInstall) {
+ remedy.setBeingInstalledRelaxedWeight(HIGH_WEIGHT);
+ } else if (!configuration.allowDifferentVersion && configuration.allowPartialInstall) {
+ remedy.setBeingInstalledRelaxedWeight(MEDIUM_WEIGHT);
+ } else if (configuration.allowDifferentVersion && configuration.allowPartialInstall) {
+ remedy.setBeingInstalledRelaxedWeight(LOW_WEIGHT);
+ } else {
+ remedy.setBeingInstalledRelaxedWeight(ZERO_WEIGHT);
+ }
+ return remedy;
+ }
+
+ @Override
+ protected String getResolveJobName() {
+ return Messages.RemediationOperation_ResolveJobName;
+ }
+
+ @Override
+ protected String getProvisioningJobName() {
+ return Messages.RemediationOperation_RemediationJobName;
+ }
+
+ public void setSelectedRemedy(Remedy remedy) {
+ this.userSelectedRemedy = remedy;
+ }
+
+ public ProvisioningJob getProvisioningJob(IProgressMonitor monitor) {
+ IStatus status = getResolutionResult();
+ // planner.resolve();
+ if (status.getSeverity() != IStatus.CANCEL && status.getSeverity() != IStatus.ERROR) {
+ if (job.getProvisioningPlan() != null) {
+ ProfileModificationJob pJob = new ProfileModificationJob(getProvisioningJobName(), session, profileId, job.getProvisioningPlan(), job.getActualProvisioningContext());
+ pJob.setAdditionalProgressMonitor(monitor);
+ return pJob;
+ }
+ }
+ return null;
+ }
+
+ public boolean hasRemedies() {
+ return (remedies != null && remedies.size() > 0);
+ }
+
+ public ProfileChangeRequest getOriginalRequest() {
+ return (ProfileChangeRequest) originalRequest;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/Remedy.java b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/Remedy.java
new file mode 100644
index 0000000..15f2a06
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/Remedy.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, 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:
+ * Red Hat, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.p2.operations;
+
+import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
+
+//TODO Javadoc
+public class Remedy {
+
+ private RemedyConfig config;
+ private ProfileChangeRequest request;
+ private int beingInstalledRelaxedWeight;
+ private int installationRelaxedWeight;
+
+ public RemedyConfig getConfig() {
+ return config;
+ }
+
+ public void setConfig(RemedyConfig config) {
+ this.config = config;
+ }
+
+ public ProfileChangeRequest getRequest() {
+ return request;
+ }
+
+ public void setRequest(ProfileChangeRequest request) {
+ this.request = request;
+ }
+
+ public int getBeingInstalledRelaxedWeight() {
+ return beingInstalledRelaxedWeight;
+ }
+
+ public void setBeingInstalledRelaxedWeight(int beingInstalledRelaxedWeight) {
+ this.beingInstalledRelaxedWeight = beingInstalledRelaxedWeight;
+ }
+
+ public int getInstallationRelaxedWeight() {
+ return installationRelaxedWeight;
+ }
+
+ public void setInstallationRelaxedWeight(int installationRelaxedWeight) {
+ this.installationRelaxedWeight = installationRelaxedWeight;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/RemedyConfig.java b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/RemedyConfig.java
new file mode 100644
index 0000000..d19ca65
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/RemedyConfig.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, 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:
+ * Red Hat, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.p2.operations;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+//TODO Javadoc
+public class RemedyConfig {
+
+ public boolean allowInstalledUpdate = false;
+ public boolean allowInstalledRemoval = false;
+ public boolean allowDifferentVersion = false;
+ public boolean allowPartialInstall = false;
+
+ public RemedyConfig() {
+
+ }
+
+ public static RemedyConfig[] getAllRemdyConfigs() {
+ Collection<RemedyConfig> remedyConfigs = new ArrayList<RemedyConfig>();
+ int allMasks = (1 << 4);
+ for (int i = 1; i < allMasks; i++) {
+ RemedyConfig remedyConfig = new RemedyConfig();
+ for (int j = 0; j < 4; j++) {
+ if ((i & (1 << j)) > 0) {
+ switch (j) {
+ case 0 :
+ remedyConfig.allowPartialInstall = true;
+ break;
+ case 1 :
+ remedyConfig.allowDifferentVersion = true;
+ break;
+ case 2 :
+ remedyConfig.allowInstalledUpdate = true;
+ break;
+ case 3 :
+ remedyConfig.allowInstalledRemoval = true;
+ break;
+ }
+ }
+
+ }
+ remedyConfigs.add(remedyConfig);
+ }
+ RemedyConfig[] test = remedyConfigs.toArray(new RemedyConfig[remedyConfigs.size()]);
+ return test;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests.ui/src/org/eclipse/equinox/p2/tests/ui/AbstractProvisioningUITest.java b/bundles/org.eclipse.equinox.p2.tests.ui/src/org/eclipse/equinox/p2/tests/ui/AbstractProvisioningUITest.java
index 3087875..3ee1b7d 100644
--- a/bundles/org.eclipse.equinox.p2.tests.ui/src/org/eclipse/equinox/p2/tests/ui/AbstractProvisioningUITest.java
+++ b/bundles/org.eclipse.equinox.p2.tests.ui/src/org/eclipse/equinox/p2/tests/ui/AbstractProvisioningUITest.java
@@ -58,8 +58,8 @@ public abstract class AbstractProvisioningUITest extends AbstractProvisioningTes
protected IInstallableUnit upgrade;
protected IInstallableUnit uninstalled;
protected IInstallableUnit category;
- private ProvisioningUI ui;
- private ServiceRegistration regLicenseManager;
+ protected ProvisioningUI ui;
+ protected ServiceRegistration regLicenseManager;
protected void setUp() throws Exception {
super.setUp();
diff --git a/bundles/org.eclipse.equinox.p2.tests.ui/src/org/eclipse/equinox/p2/tests/ui/dialogs/RemediationTest.java b/bundles/org.eclipse.equinox.p2.tests.ui/src/org/eclipse/equinox/p2/tests/ui/dialogs/RemediationTest.java
new file mode 100644
index 0000000..1b8905e
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests.ui/src/org/eclipse/equinox/p2/tests/ui/dialogs/RemediationTest.java
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2013 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
+ * Ericsson AB (Hamdan Msheik) - Bypass install license wizard page via plugin_customization
+ *******************************************************************************/
+package org.eclipse.equinox.p2.tests.ui.dialogs;
+
+import java.io.File;
+import java.net.URI;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import org.eclipse.equinox.internal.p2.metadata.InstallableUnit;
+import org.eclipse.equinox.internal.p2.ui.ProvUI;
+import org.eclipse.equinox.internal.p2.ui.dialogs.*;
+import org.eclipse.equinox.internal.p2.ui.model.ProfileElement;
+import org.eclipse.equinox.internal.p2.ui.sdk.SimpleLicenseManager;
+import org.eclipse.equinox.p2.metadata.*;
+import org.eclipse.equinox.p2.operations.Update;
+import org.eclipse.equinox.p2.operations.UpdateOperation;
+import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
+import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
+import org.eclipse.equinox.p2.tests.*;
+import org.eclipse.equinox.p2.ui.*;
+import org.eclipse.jface.wizard.WizardDialog;
+import org.osgi.framework.Constants;
+
+/**
+ * Tests for the install wizard
+ */
+public class RemediationTest extends WizardTest {
+
+ // private static final String AVAILABLE_SOFTWARE_PAGE = "AvailableSoftwarePage";
+ // private static final String MAIN_IU = "MainIU";
+ public static final int INSTALLATION_SUCCEEDED = 1;
+ public static final int INSTALLATION_REMEDIATED = 2;
+ public static final int INSTALLATION_FAILED = 3;
+ public static final int CHECK_FOR_UPDATES = 4;
+ public static final int UPDATE_ONE_IU = 5;
+ private String name = "PROFILE_";
+
+ @IUDescription(content = "package: jboss \n" + "singleton: true\n" + "version: 6 \n" + "depends: m2e = 2")
+ public IInstallableUnit jboss60;
+
+ @IUDescription(content = "package: jboss \n" + "singleton: true\n" + "version: 5 \n" + "depends: m2e = 1")
+ public IInstallableUnit jboss55;
+
+ @IUDescription(content = "package: m2e \n" + "singleton: true\n" + "version: 1 \n")
+ public IInstallableUnit m2e11;
+
+ @IUDescription(content = "package: m2e \n" + "singleton: true\n" + "version: 2 \n")
+ public IInstallableUnit m2e12;
+
+ IInstallableUnit toInstall;
+
+ public void setUp() throws Exception {
+ }
+
+ public void visibleSetup(int type) throws Exception {
+ //Clearout repositories
+ name = "PROFILE_" + type;
+ URI[] repos = getMetadataRepositoryManager().getKnownRepositories(IMetadataRepositoryManager.REPOSITORIES_ALL);
+ for (URI uri : repos) {
+ getMetadataRepositoryManager().removeRepository(uri);
+ }
+
+ // create test profile
+ profile = createProfile(name);
+
+ // copy of provisioning UI that uses a different profile
+ ui = ProvisioningUI.getDefaultUI();
+ ui = new ProvisioningUI(ui.getSession(), name, ui.getPolicy());
+ ui.getOperationRunner().suppressRestart(true);
+ ui.getPolicy().setRepositoriesVisible(false);
+
+ // register alternate services
+ SimpleLicenseManager manager = new SimpleLicenseManager(name);
+ Dictionary<String, Object> properties = new Hashtable<String, Object>(5);
+ properties.put(Constants.SERVICE_RANKING, new Integer(1));
+ regLicenseManager = TestActivator.getContext().registerService(LicenseManager.class.getName(), manager, properties);
+ profileElement = new ProfileElement(null, name);
+ IULoader.loadIUs(this);
+ ILicense[] licenses = new ILicense[] {MetadataFactory.createLicense(URI.create("http://eclipse.org"), "license text"), MetadataFactory.createLicense(URI.create("http://apache.org"), "license text2")};
+ ((InstallableUnit) jboss60).setLicenses(licenses);
+ switch (type) {
+ case INSTALLATION_SUCCEEDED :
+ createTestMetdataRepository(new IInstallableUnit[] {jboss60, m2e11, m2e12});
+ install(m2e12, true, false);
+ toInstall = jboss60;
+ break;
+ case INSTALLATION_REMEDIATED :
+ createTestMetdataRepository(new IInstallableUnit[] {jboss60, m2e11, m2e12});
+ install(m2e11, true, false);
+ toInstall = jboss60;
+ break;
+ case INSTALLATION_FAILED :
+ createTestMetdataRepository(new IInstallableUnit[] {jboss60, m2e11});
+ install(m2e11, true, false);
+ toInstall = jboss60;
+ break;
+ case CHECK_FOR_UPDATES :
+ createTestMetdataRepository(new IInstallableUnit[] {jboss60, m2e11, m2e12});
+ install(m2e11, true, false);
+ break;
+ case UPDATE_ONE_IU :
+ createTestMetdataRepository(new IInstallableUnit[] {jboss55, jboss60, m2e11, m2e12});
+ install(jboss55, true, false);
+ install(m2e11, true, false);
+ break;
+ default :
+ createTestMetdataRepository(new IInstallableUnit[] {jboss60, m2e11});
+ install(m2e11, true, false);
+
+ }
+
+ metaManager = (IMetadataRepositoryManager) getAgent().getService(IMetadataRepositoryManager.SERVICE_NAME);
+ artifactManager = (IArtifactRepositoryManager) getAgent().getService(IArtifactRepositoryManager.SERVICE_NAME);
+ File site = new File(TestActivator.getTestDataFolder().toString(), TEST_REPO_PATH);
+ testRepoLocation = site.toURI();
+ metaManager.addRepository(testRepoLocation);
+ artifactManager.addRepository(testRepoLocation);
+ }
+
+ public void testInstallWizard() throws Exception {
+ LoadMetadataRepositoryJob job = new LoadMetadataRepositoryJob(getProvisioningUI());
+ getPolicy().setGroupByCategory(false);
+ getPolicy().setShowLatestVersionsOnly(false);
+ job.runModal(getMonitor());
+ InstallWizard wizard = new InstallWizard(getProvisioningUI(), null, null, job);
+ WizardDialog dialog = new ProvisioningWizardDialog(ProvUI.getDefaultParentShell(), wizard);
+
+ dialog.create();
+ dialog.setBlockOnOpen(false);
+ dialog.open();
+
+ }
+
+ public void testUpdateWizard() throws Exception {
+ LoadMetadataRepositoryJob job = new LoadMetadataRepositoryJob(getProvisioningUI());
+ getPolicy().setGroupByCategory(false);
+ getPolicy().setShowLatestVersionsOnly(false);
+ job.runModal(getMonitor());
+ UpdateOperation op = new UpdateOperation(getSession());
+ op.setProfileId(name);
+ op.resolveModal(getMonitor());
+ UpdateWizard wizard = new UpdateWizard(getProvisioningUI(), op, new Update[] {}, job);
+ WizardDialog dialog = new ProvisioningWizardDialog(ProvUI.getDefaultParentShell(), wizard);
+ dialog.create();
+ dialog.setBlockOnOpen(false);
+ dialog.open();
+ }
+}
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 118d5cf..7a64aeb 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
@@ -1350,6 +1350,10 @@ public abstract class AbstractProvisioningTest extends TestCase {
assertNotContains(null, result, value);
}
+ // public void assertContains(IQueryable<IInstallableUnit> queryable, IInstallableUnit iu) {
+ // assertFalse("Missing IU " + iu.toString(), queryable.query(QueryUtil.ALL_UNITS, null).isEmpty());
+ // }
+
public static void assertContains(String message, IQueryResult result, Object value) {
Iterator itor = result.iterator();
while (itor.hasNext())
@@ -1715,4 +1719,9 @@ public abstract class AbstractProvisioningTest extends TestCase {
//ignore
}
}
+
+ public void assertResolve(IProfileChangeRequest request, IPlanner planner) {
+ IProvisioningPlan plan = planner.getProvisioningPlan(request, null, null);
+ assertOK(plan.getStatus());
+ }
}
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
index 1f2917f..22b1262 100644
--- 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
@@ -218,6 +218,7 @@ public class ReducedCUDFParser {
// if (currentIU.isInstalled()) {
// keepRequests.addAll(currentKeepRequests);
// }
+ currentIU.setProperty(InstallableUnitDescription.PROP_TYPE_GROUP, "true");
allIUs.add(MetadataFactory.createInstallableUnit(currentIU));
// reset to be ready for the next stanza
currentIU = null;
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/AllAnyVersionTests.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/AllAnyVersionTests.java
new file mode 100644
index 0000000..cf742e7
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/AllAnyVersionTests.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, 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:
+ * Red Hat, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.p2.tests.planner;
+
+import junit.framework.*;
+
+public class AllAnyVersionTests extends TestCase {
+
+ public static Test suite() {
+ TestSuite suite = new TestSuite(AllAnyVersionTests.class.getName());
+ suite.addTestSuite(TestRequestFlexerIUProperties.class);
+ suite.addTestSuite(TestRequestFlexerOneInstalledOneBeingInstalled.class);
+ suite.addTestSuite(TestRequestFlexerOneInstalledReplacingIt.class);
+ suite.addTestSuite(TestRequestFlexerOneInstalledTwoBeingInstalled.class);
+ suite.addTestSuite(TestRequestFlexerRequestWithOptionalInstall.class);
+ suite.addTestSuite(TestRequestFlexerRequestWithRemoval.class);
+ return suite;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/Bug306279c.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/Bug306279c.java
index 20d5b75..6adb2ad 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/Bug306279c.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/Bug306279c.java
@@ -27,7 +27,7 @@ public class Bug306279c extends AbstractProvisioningTest {
IInstallableUnit x, y, a1, a2, b;
x = createIU("X");
- //Y -ng-> X
+ //Y -ng & op-> X
IRequirement[] reqY = new IRequirement[1];
reqY[0] = MetadataFactory.createRequirement(IInstallableUnit.NAMESPACE_IU_ID, "X", VersionRange.emptyRange, null, true, false, false);
y = createIU("Y", Version.create("1.0.0"), reqY);
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/JBoss.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/JBoss.java
new file mode 100644
index 0000000..5b48b2f
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/JBoss.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * 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.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.planner.IProfileChangeRequest;
+import org.eclipse.equinox.p2.tests.*;
+
+public class JBoss extends AbstractProvisioningTest {
+ @IUDescription(content = "package: jboss \n" + "singleton: true\n" + "version: 6 \n" + "depends: m2e = 12")
+ public IInstallableUnit jboss;
+
+ @IUDescription(content = "package: m2e \n" + "singleton: true\n" + "version: 11 \n")
+ public IInstallableUnit m2e11;
+
+ @IUDescription(content = "package: m2e \n" + "singleton: true\n" + "version: 12 \n")
+ public IInstallableUnit m2e12;
+
+ IProfile profile = createProfile("TestProfile." + getClass().getSimpleName());
+
+ private IPlanner planner;
+
+ private IEngine engine;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ IULoader.loadIUs(this);
+ createTestMetdataRepository(new IInstallableUnit[] {jboss, m2e11, m2e12});
+ planner = createPlanner();
+ engine = createEngine();
+ assertOK(install(profile, new IInstallableUnit[] {m2e11}, true, planner, engine));
+ }
+
+ public void testInstallJBoss() {
+ ProfileChangeRequest installJBoss = new ProfileChangeRequest(profile);
+ installJBoss.add(jboss);
+ assertNotOK(install(installJBoss, planner, engine));
+
+ IProfileChangeRequest res = new LuckyHelper().computeProfileChangeRequest(profile, planner, installJBoss, new ProvisioningContext(getAgent()), getMonitor());
+ assertTrue(res.getAdditions().contains(m2e12));
+ assertTrue(res.getRemovals().contains(m2e11));
+
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerIUProperties.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerIUProperties.java
new file mode 100644
index 0000000..598cc39
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerIUProperties.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, 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:
+ * Red Hat, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.p2.tests.planner;
+
+import java.util.Map;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
+import org.eclipse.equinox.internal.p2.operations.RequestFlexer;
+import org.eclipse.equinox.p2.engine.*;
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.planner.*;
+import org.eclipse.equinox.p2.tests.*;
+
+public class TestRequestFlexerIUProperties extends AbstractProvisioningTest {
+ 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$
+
+ @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" + "depends: platform = 1")
+ public IInstallableUnit egit1;
+
+ @IUDescription(content = "package: egit \n" + "singleton: true\n" + "version: 2 \n" + "depends: platform = 2")
+ public IInstallableUnit egit2;
+
+ @IUDescription(content = "package: egit \n" + "singleton: true\n" + "version: 3 \n" + "depends: platform = 3")
+ public IInstallableUnit egit3;
+
+ IProfile profile;
+
+ private IPlanner planner;
+
+ private IEngine engine;
+
+ private ProvisioningContext context;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ IULoader.loadIUs(this);
+ createTestMetdataRepository(new IInstallableUnit[] {sdk1, platform1});
+ planner = createPlanner();
+ engine = createEngine();
+ context = new ProvisioningContext(getAgent());
+ }
+
+ public void testWithChanginRootFromOptionalToStrict() {
+ profile = createProfile("TestProfile." + getName());
+ assertOK(installAsRoots(profile, new IInstallableUnit[] {sdk1}, false, planner, engine));
+ createTestMetdataRepository(new IInstallableUnit[] {sdk1, platform1, sdk2, platform2, egit1, egit2});
+
+ IProfileChangeRequest originalRequest = planner.createChangeRequest(profile);
+ originalRequest.add(egit2);
+ originalRequest.setInstallableUnitInclusionRules(egit2, ProfileInclusionRules.createStrictInclusionRule(egit2));
+ originalRequest.setInstallableUnitInclusionRules(sdk1, ProfileInclusionRules.createStrictInclusionRule(sdk1));
+ assertNotOK(planner.getProvisioningPlan(originalRequest, null, null).getStatus());
+
+ {
+ //sdk1 is requested to be marked strict, so since sdk1 and egit can't be installed together and we don't have any flexibility, we get null
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ assertNull(realRequest);
+ }
+
+ {
+ //Verify that it is possible to install egit2 because the sdk1 is optional
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowInstalledElementChange(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ assertTrue(realRequest.getAdditions().contains(egit2));
+ assertTrue(realRequest.getAdditions().contains(sdk2));
+ assertTrue(realRequest.getRemovals().contains(sdk1));
+ assertEquals(2, realRequest.getAdditions().size());
+ assertEquals(1, realRequest.getRemovals().size());
+ }
+ }
+
+ public void testWithChanginRootFromOptionalToStrictByRemovingIUProperty() {
+ profile = createProfile("TestProfile." + getName());
+ assertOK(installAsRoots(profile, new IInstallableUnit[] {sdk1}, false, planner, engine));
+ createTestMetdataRepository(new IInstallableUnit[] {sdk1, platform1, sdk2, platform2, egit1, egit2});
+
+ IProfileChangeRequest originalRequest = planner.createChangeRequest(profile);
+ originalRequest.add(egit2);
+ originalRequest.setInstallableUnitInclusionRules(egit2, ProfileInclusionRules.createStrictInclusionRule(egit2));
+ originalRequest.removeInstallableUnitInclusionRules(sdk1);
+ assertNotOK(planner.getProvisioningPlan(originalRequest, null, null).getStatus());
+
+ {
+ //Verify that it is possible to install egit2 because the sdk1 is optional
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowInstalledElementChange(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ assertTrue(realRequest.getAdditions().contains(egit2));
+ assertTrue(realRequest.getAdditions().contains(sdk2));
+ assertTrue(realRequest.getRemovals().contains(sdk1));
+ assertEquals(2, realRequest.getAdditions().size());
+ assertEquals(1, realRequest.getRemovals().size());
+ }
+ }
+
+ public void testWithChanginRootFromStrictToOptional() {
+ profile = createProfile("TestProfile." + getName());
+ assertOK(installAsRoots(profile, new IInstallableUnit[] {sdk1}, true, planner, engine));
+ createTestMetdataRepository(new IInstallableUnit[] {sdk1, platform1, sdk2, platform2, egit1, egit2});
+
+ IProfileChangeRequest originalRequest = planner.createChangeRequest(profile);
+ originalRequest.add(egit2);
+ originalRequest.setInstallableUnitInclusionRules(egit2, ProfileInclusionRules.createStrictInclusionRule(egit2));
+ originalRequest.setInstallableUnitInclusionRules(sdk1, ProfileInclusionRules.createOptionalInclusionRule(sdk1));
+ assertOK(planner.getProvisioningPlan(originalRequest, null, null).getStatus());
+
+ {
+ //Verify that it is possible to install egit2 because the sdk1 inclusion is change to optional
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ assertTrue(realRequest.getAdditions().contains(egit2));
+ assertTrue(realRequest.getRemovals().contains(sdk1));
+ assertEquals(1, realRequest.getAdditions().size());
+ assertEquals(1, realRequest.getRemovals().size());
+ assertResolve(realRequest, planner);
+ }
+
+ {
+ //Verify that it is possible to install egit2 because the sdk1 inclusion is change to optional
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowInstalledElementChange(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ assertTrue(realRequest.getAdditions().contains(egit2));
+ assertTrue(realRequest.getAdditions().contains(sdk2));
+ assertTrue(realRequest.getRemovals().contains(sdk1));
+ assertEquals(2, realRequest.getAdditions().size());
+ assertEquals(1, realRequest.getRemovals().size());
+ assertResolve(realRequest, planner);
+ assertTrue(isOptionallyBeingInstalled(sdk2, realRequest));
+ }
+
+ }
+
+ public void testRandomIUProperty() {
+ profile = createProfile("TestProfile." + getName());
+ assertOK(installAsRoots(profile, new IInstallableUnit[] {sdk1}, true, planner, engine));
+ createTestMetdataRepository(new IInstallableUnit[] {sdk1, platform1, sdk2, platform2, egit1, egit2});
+
+ IProfileChangeRequest originalRequest = planner.createChangeRequest(profile);
+ originalRequest.add(egit3);
+ originalRequest.setInstallableUnitInclusionRules(egit3, ProfileInclusionRules.createStrictInclusionRule(egit3));
+ originalRequest.setInstallableUnitProfileProperty(egit3, "MYKEY", "MYVALUE");
+ assertNotOK(planner.getProvisioningPlan(originalRequest, null, null).getStatus());
+
+ //Verify that it is possible to install egit2 because the sdk1 inclusion is change to optional
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowDifferentVersion(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ assertTrue(realRequest.getAdditions().contains(egit1));
+ assertEquals(1, realRequest.getAdditions().size());
+ assertResolve(realRequest, planner);
+ assertKeyValue(egit1, "MYKEY", "MYVALUE", realRequest);
+ }
+
+ private void assertKeyValue(IInstallableUnit iu, String key, String value, IProfileChangeRequest request) {
+ Map<String, String> match = ((ProfileChangeRequest) request).getInstallableUnitProfilePropertiesToAdd().get(iu);
+ assertNotNull(match);
+ assertEquals(value, match.get(key));
+ }
+
+ private boolean isOptionallyBeingInstalled(IInstallableUnit iu, IProfileChangeRequest request) {
+ Map<String, String> match = ((ProfileChangeRequest) request).getInstallableUnitProfilePropertiesToAdd().get(iu);
+ if (match == null)
+ return false;
+ return INCLUSION_OPTIONAL.equals(match.get(INCLUSION_RULES));
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerOneInstalledOneBeingInstalled.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerOneInstalledOneBeingInstalled.java
new file mode 100644
index 0000000..6c903a9
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerOneInstalledOneBeingInstalled.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, 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:
+ * Red Hat, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.p2.tests.planner;
+
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.equinox.internal.p2.operations.RequestFlexer;
+import org.eclipse.equinox.p2.engine.*;
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.planner.*;
+import org.eclipse.equinox.p2.tests.*;
+
+public class TestRequestFlexerOneInstalledOneBeingInstalled 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" + "depends: platform = 1")
+ public IInstallableUnit egit1;
+
+ @IUDescription(content = "package: egit \n" + "singleton: true\n" + "version: 2 \n" + "depends: platform = 2")
+ public IInstallableUnit egit2;
+
+ @IUDescription(content = "package: svn1 \n" + "singleton: true\n" + "version: 1 \n" + "depends: platform = 1")
+ public IInstallableUnit svn1;
+
+ @IUDescription(content = "package: svn2 \n" + "singleton: true\n" + "version: 2 \n" + "depends: platform = 2")
+ public IInstallableUnit svn2;
+
+ IProfile profile;
+
+ private IPlanner planner;
+
+ private IEngine engine;
+
+ private IProfileChangeRequest originalRequest;
+
+ private ProvisioningContext context;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ profile = createProfile("TestProfile." + getName());
+ IULoader.loadIUs(this);
+ createTestMetdataRepository(new IInstallableUnit[] {sdk1, platform1, sdk2, platform2, egit1, egit2});
+ planner = createPlanner();
+ engine = createEngine();
+ assertOK(install(profile, new IInstallableUnit[] {sdk1}, true, planner, engine));
+
+ originalRequest = planner.createChangeRequest(profile);
+ originalRequest.add(egit2);
+ originalRequest.setInstallableUnitInclusionRules(egit2, ProfileInclusionRules.createStrictInclusionRule(egit2));
+ assertNotOK(planner.getProvisioningPlan(originalRequest, context, null).getStatus());
+
+ {
+ //Make sure that the goal we are after can actually be reached
+ IProfileChangeRequest validateGoalRequest = planner.createChangeRequest(profile);
+ validateGoalRequest.add(egit2);
+ validateGoalRequest.setInstallableUnitInclusionRules(egit2, ProfileInclusionRules.createStrictInclusionRule(egit2));
+ validateGoalRequest.add(sdk2);
+ validateGoalRequest.setInstallableUnitInclusionRules(sdk2, ProfileInclusionRules.createStrictInclusionRule(sdk2));
+ validateGoalRequest.remove(sdk1);
+ assertOK(planner.getProvisioningPlan(validateGoalRequest, context, null).getStatus());
+ }
+
+ {
+ //Make sure that the goal we are after can actually be reached
+ IProfileChangeRequest validateGoalRequest = planner.createChangeRequest(profile);
+ validateGoalRequest.add(egit1);
+ validateGoalRequest.setInstallableUnitInclusionRules(egit1, ProfileInclusionRules.createStrictInclusionRule(egit1));
+ assertOK(planner.getProvisioningPlan(validateGoalRequest, context, null).getStatus());
+ }
+ context = new ProvisioningContext(getAgent());
+
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ getProfileRegistry().removeProfile(profile.getProfileId());
+ }
+
+ //Found a solution by installing a previous version
+ public void testInstallAnotherVersion() {
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowDifferentVersion(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ assertTrue(realRequest.getAdditions().contains(egit1));
+ assertEquals(1, realRequest.getAdditions().size());
+ assertTrue(realRequest.getRemovals().isEmpty());
+ assertOK(install(realRequest, planner, engine));
+ }
+
+ public void testInstallPartial() {
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowPartialInstall(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ assertNull(realRequest);
+ }
+
+ public void testInstallSomeElementsWithUpdates() {
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowPartialInstall(true);
+ av.setAllowDifferentVersion(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ assertTrue(realRequest.getAdditions().contains(egit1));
+ assertEquals(1, realRequest.getAdditions().size());
+ assertTrue(realRequest.getRemovals().isEmpty());
+ assertOK(install(realRequest, planner, engine));
+ }
+
+ //Found a solution by changing the base
+ public void testUpdateBase() {
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowInstalledElementChange(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ assertTrue(realRequest.getAdditions().contains(egit2));
+ assertTrue(realRequest.getAdditions().contains(sdk2));
+ assertEquals(2, realRequest.getAdditions().size());
+ assertTrue(realRequest.getRemovals().contains(sdk1));
+ assertEquals(1, realRequest.getRemovals().size());
+ assertOK(install(realRequest, planner, engine));
+ }
+
+ //Found a solution by removing the base - in this case only the new element is installed
+ public void testRemoveBase() {
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowInstalledElementRemoval(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ assertTrue(realRequest.getAdditions().contains(egit2));
+ assertTrue(realRequest.getRemovals().contains(sdk1));
+ assertOK(install(realRequest, planner, engine));
+ }
+
+ public void testAllowEverything() {
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowPartialInstall(true);
+ av.setAllowDifferentVersion(true);
+ av.setAllowInstalledElementRemoval(true);
+ av.setAllowInstalledElementChange(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ //We only sdk1 because our goal is maximize the number of installed element and minimize the number of changes
+ assertTrue(realRequest.getAdditions().contains(egit1));
+ assertTrue(realRequest.getRemovals().isEmpty());
+ assertOK(install(realRequest, planner, engine));
+ }
+
+ public void testDoNothing() {
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ assertNull(realRequest);
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerOneInstalledReplacingIt.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerOneInstalledReplacingIt.java
new file mode 100644
index 0000000..b57f5a3
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerOneInstalledReplacingIt.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, 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:
+ * Red Hat, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.p2.tests.planner;
+
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.equinox.internal.p2.operations.RequestFlexer;
+import org.eclipse.equinox.p2.engine.*;
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.planner.*;
+import org.eclipse.equinox.p2.tests.*;
+
+public class TestRequestFlexerOneInstalledReplacingIt 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;
+
+ private IPlanner planner;
+
+ private IEngine engine;
+
+ private IProfileChangeRequest originalRequest;
+
+ private ProvisioningContext context;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ profile = createProfile("TestProfile." + getName());
+ IULoader.loadIUs(this);
+ createTestMetdataRepository(new IInstallableUnit[] {sdk1, platform1, sdk2, platform2});
+ planner = createPlanner();
+ engine = createEngine();
+ assertOK(install(profile, new IInstallableUnit[] {sdk1}, true, planner, engine));
+
+ originalRequest = planner.createChangeRequest(profile);
+ originalRequest.add(sdk2);
+ originalRequest.setInstallableUnitInclusionRules(sdk2, ProfileInclusionRules.createStrictInclusionRule(sdk2));
+ assertNotOK(planner.getProvisioningPlan(originalRequest, context, null).getStatus());
+
+ context = new ProvisioningContext(getAgent());
+
+ }
+
+ public void testRemoveInstalledElement() {
+ IProfileChangeRequest requestToTest = planner.createChangeRequest(profile);
+ requestToTest.add(sdk2);
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowInstalledElementRemoval(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(requestToTest, profile, new NullProgressMonitor());
+ assertTrue(realRequest.getRemovals().contains(sdk1));
+ assertTrue(realRequest.getAdditions().contains(sdk2));
+ assertEquals(1, realRequest.getRemovals().size());
+ assertOK(install(realRequest, planner, engine));
+ }
+
+ public void testUpdateInstalledElement() {
+ IProfileChangeRequest requestToTest = planner.createChangeRequest(profile);
+ requestToTest.add(sdk2);
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowInstalledElementChange(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(requestToTest, profile, new NullProgressMonitor());
+ assertTrue(realRequest.getRemovals().contains(sdk1));
+ assertTrue(realRequest.getAdditions().contains(sdk2));
+ assertEquals(1, realRequest.getRemovals().size());
+ assertEquals(1, realRequest.getAdditions().size());
+ assertOK(install(realRequest, planner, engine));
+ }
+
+ public void testUDifferentVersionAndUpdateInstalledElement() {
+ IProfileChangeRequest requestToTest = planner.createChangeRequest(profile);
+ requestToTest.add(sdk2);
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowDifferentVersion(true);
+ av.setAllowInstalledElementChange(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(requestToTest, profile, new NullProgressMonitor());
+ assertTrue(realRequest.getRemovals().contains(sdk1));
+ assertTrue(realRequest.getAdditions().contains(sdk2));
+ assertEquals(1, realRequest.getRemovals().size());
+ assertEquals(1, realRequest.getAdditions().size());
+ assertOK(install(realRequest, planner, engine));
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerOneInstalledTwoBeingInstalled.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerOneInstalledTwoBeingInstalled.java
new file mode 100644
index 0000000..7b950d3
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerOneInstalledTwoBeingInstalled.java
@@ -0,0 +1,171 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, 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:
+ * Red Hat, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.p2.tests.planner;
+
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.equinox.internal.p2.operations.RequestFlexer;
+import org.eclipse.equinox.p2.engine.*;
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.planner.*;
+import org.eclipse.equinox.p2.tests.*;
+
+public class TestRequestFlexerOneInstalledTwoBeingInstalled 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" + "depends: platform = 1")
+ public IInstallableUnit egit1;
+
+ @IUDescription(content = "package: egit \n" + "singleton: true\n" + "version: 2 \n" + "depends: platform = 2")
+ public IInstallableUnit egit2;
+
+ @IUDescription(content = "package: egit \n" + "singleton: true\n" + "version: 3 \n" + "depends: platform = 3")
+ public IInstallableUnit egit3;
+
+ @IUDescription(content = "package: svn \n" + "singleton: true\n" + "version: 1 \n" + "depends: platform = 1")
+ public IInstallableUnit svn1;
+
+ @IUDescription(content = "package: svn \n" + "singleton: true\n" + "version: 2 \n" + "depends: platform = 2")
+ public IInstallableUnit svn2;
+
+ @IUDescription(content = "package: svn \n" + "singleton: true\n" + "version: 3 \n" + "depends: platform = 3")
+ public IInstallableUnit svn3;
+
+ IProfile profile;
+
+ private IPlanner planner;
+
+ private IEngine engine;
+
+ private ProvisioningContext context;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ profile = createProfile("TestProfile." + getName());
+ IULoader.loadIUs(this);
+ createTestMetdataRepository(new IInstallableUnit[] {sdk1, platform1});
+ planner = createPlanner();
+ engine = createEngine();
+ context = new ProvisioningContext(getAgent());
+ assertOK(install(profile, new IInstallableUnit[] {sdk1}, true, planner, engine));
+ }
+
+ public void testAssumptions() {
+ IProfileChangeRequest originalRequest = planner.createChangeRequest(profile);
+ originalRequest.add(egit2);
+ originalRequest.setInstallableUnitInclusionRules(egit2, ProfileInclusionRules.createStrictInclusionRule(egit2));
+ originalRequest.add(svn1);
+ originalRequest.setInstallableUnitInclusionRules(svn1, ProfileInclusionRules.createStrictInclusionRule(svn1));
+ assertNotOK(planner.getProvisioningPlan(originalRequest, context, null).getStatus());
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ getProfileRegistry().removeProfile(profile.getProfileId());
+ }
+
+ public void testConflictWithTheBase() {
+ createTestMetdataRepository(new IInstallableUnit[] {sdk1, platform1, sdk2, platform2, egit1, egit2, egit3, svn1, svn2, svn3});
+
+ IProfileChangeRequest originalRequest = planner.createChangeRequest(profile);
+ originalRequest.add(egit2);
+ originalRequest.setInstallableUnitInclusionRules(egit2, ProfileInclusionRules.createStrictInclusionRule(egit2));
+ originalRequest.add(svn1);
+ originalRequest.setInstallableUnitInclusionRules(svn1, ProfileInclusionRules.createStrictInclusionRule(svn1));
+
+ {
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowDifferentVersion(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ assertTrue(realRequest.getAdditions().contains(egit1));
+ assertTrue(realRequest.getAdditions().contains(svn1));
+ assertEquals(2, realRequest.getAdditions().size());
+ assertTrue(realRequest.getRemovals().isEmpty());
+ assertResolve(realRequest, planner);
+ }
+
+ {
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowPartialInstall(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ assertTrue(realRequest.getAdditions().contains(svn1));
+ assertEquals(1, realRequest.getAdditions().size());
+ assertTrue(realRequest.getRemovals().isEmpty());
+ }
+
+ {
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowInstalledElementChange(true);
+ av.setAllowDifferentVersion(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ assertTrue(realRequest.getAdditions().contains(svn1));
+ assertTrue(realRequest.getAdditions().contains(egit1));
+ assertEquals(2, realRequest.getAdditions().size());
+ assertTrue(realRequest.getRemovals().isEmpty());
+ }
+ }
+
+ // public void testOneElementWithMissingRequirement() {
+ // createTestMetdataRepository(new IInstallableUnit[] {sdk1, platform1, sdk2, platform2, egit1, egit2, egit3, svn1, svn2});
+ //
+ // IProfileChangeRequest originalRequest = planner.createChangeRequest(profile);
+ // originalRequest.add(egit3); //This is the element for which we have a missing requirement
+ // originalRequest.setInstallableUnitInclusionRules(egit3, ProfileInclusionRules.createStrictInclusionRule(egit3));
+ // originalRequest.add(svn1);
+ // originalRequest.setInstallableUnitInclusionRules(svn1, ProfileInclusionRules.createStrictInclusionRule(svn1));
+ //
+ // {
+ // AnyVersion2 av = new AnyVersion2(planner);
+ // av.setAllowPartialInstall(true);
+ // av.setProvisioningContext(context);
+ // IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ // assertTrue(realRequest.getAdditions().contains(svn1));
+ // assertEquals(1, realRequest.getAdditions().size());
+ // assertTrue(realRequest.getRemovals().isEmpty());
+ // }
+ //
+ // {
+ // AnyVersion2 av = new AnyVersion2(planner);
+ // av.setAllowDifferentVersion(true);
+ // av.setProvisioningContext(context);
+ // IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ // assertTrue(realRequest.getAdditions().contains(svn2));
+ // assertTrue(realRequest.getAdditions().contains(egit2));
+ // assertTrue(realRequest.getRemovals().isEmpty());
+ // }
+ //
+ // {
+ // AnyVersion2 av = new AnyVersion2(planner);
+ // av.setAllowInstalledElementChange(true);
+ // av.setAllowDifferentVersion(true);
+ // av.setProvisioningContext(context);
+ // IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ // assertTrue(realRequest.getAdditions().contains(svn2));
+ // assertTrue(realRequest.getAdditions().contains(egit2));
+ // assertTrue(realRequest.getRemovals().isEmpty());
+ // }
+ // }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerRequestWithOptionalInstall.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerRequestWithOptionalInstall.java
new file mode 100644
index 0000000..f09b848
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerRequestWithOptionalInstall.java
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, 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:
+ * Red Hat, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.p2.tests.planner;
+
+import java.util.Map;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
+import org.eclipse.equinox.internal.p2.operations.RequestFlexer;
+import org.eclipse.equinox.p2.engine.*;
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.planner.*;
+import org.eclipse.equinox.p2.tests.*;
+
+public class TestRequestFlexerRequestWithOptionalInstall extends AbstractProvisioningTest {
+ 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$
+
+ @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" + "depends: platform = 1")
+ public IInstallableUnit egit1;
+
+ @IUDescription(content = "package: egit \n" + "singleton: true\n" + "version: 2 \n" + "depends: platform = 2")
+ public IInstallableUnit egit2;
+
+ @IUDescription(content = "package: egit \n" + "singleton: true\n" + "version: 3 \n" + "depends: platform = 3")
+ public IInstallableUnit egit3;
+
+ IProfile profile;
+
+ private IPlanner planner;
+
+ private IEngine engine;
+
+ private ProvisioningContext context;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ profile = createProfile("TestProfile." + getName());
+ IULoader.loadIUs(this);
+ createTestMetdataRepository(new IInstallableUnit[] {sdk1, platform1});
+ planner = createPlanner();
+ engine = createEngine();
+ context = new ProvisioningContext(getAgent());
+ assertOK(installAsRoots(profile, new IInstallableUnit[] {sdk1}, true, planner, engine));
+ }
+
+ public void testWithOptionalInstall() {
+ createTestMetdataRepository(new IInstallableUnit[] {sdk1, platform1, sdk2, platform2, egit1, egit2, egit3});
+
+ IProfileChangeRequest originalRequest = planner.createChangeRequest(profile);
+ originalRequest.add(egit2);
+ originalRequest.setInstallableUnitInclusionRules(egit2, ProfileInclusionRules.createOptionalInclusionRule(egit2));
+
+ {
+ //The request is unsatisfiable is no flexibility is given
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ assertNull(realRequest);
+ }
+
+ {
+ //The base is allowed to change so egit2 will install fine
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowInstalledElementChange(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ assertTrue(realRequest.getAdditions().contains(egit2));
+ assertTrue(realRequest.getAdditions().contains(sdk2));
+ assertEquals(2, realRequest.getAdditions().size());
+ assertTrue(realRequest.getRemovals().contains(sdk1));
+ assertResolve(realRequest, planner);
+ }
+
+ {
+ //We allow for a different version to be installed, so egit1 will be installed
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setAllowDifferentVersion(true);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ assertTrue(realRequest.getAdditions().contains(egit1));
+ assertEquals(1, realRequest.getAdditions().size());
+ assertTrue(isOptionallyBeingInstalled(egit1, realRequest));
+ assertResolve(realRequest, planner);
+ }
+ }
+
+ private boolean isOptionallyBeingInstalled(IInstallableUnit iu, IProfileChangeRequest originalRequest) {
+ Map<String, String> match = ((ProfileChangeRequest) originalRequest).getInstallableUnitProfilePropertiesToAdd().get(iu);
+ if (match == null)
+ return false;
+ return INCLUSION_OPTIONAL.equals(match.get(INCLUSION_RULES));
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ getProfileRegistry().removeProfile(profile.getProfileId());
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerRequestWithRemoval.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerRequestWithRemoval.java
new file mode 100644
index 0000000..571d68c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/planner/TestRequestFlexerRequestWithRemoval.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Red Hat, 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:
+ * Red Hat, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.p2.tests.planner;
+
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.equinox.internal.p2.operations.RequestFlexer;
+import org.eclipse.equinox.p2.engine.*;
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.planner.*;
+import org.eclipse.equinox.p2.tests.*;
+
+public class TestRequestFlexerRequestWithRemoval 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" + "depends: platform = 1")
+ public IInstallableUnit egit1;
+
+ @IUDescription(content = "package: egit \n" + "singleton: true\n" + "version: 2 \n" + "depends: platform = 2")
+ public IInstallableUnit egit2;
+
+ @IUDescription(content = "package: egit \n" + "singleton: true\n" + "version: 3 \n" + "depends: platform = 3")
+ public IInstallableUnit egit3;
+
+ IProfile profile;
+
+ private IPlanner planner;
+
+ private IEngine engine;
+
+ private ProvisioningContext context;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ profile = createProfile("TestProfile." + getName());
+ IULoader.loadIUs(this);
+ createTestMetdataRepository(new IInstallableUnit[] {sdk1, platform1});
+ planner = createPlanner();
+ engine = createEngine();
+ context = new ProvisioningContext(getAgent());
+ assertOK(install(profile, new IInstallableUnit[] {sdk1}, true, planner, engine));
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ getProfileRegistry().removeProfile(profile.getProfileId());
+ }
+
+ public void testWithRemovalInChangeRequest() {
+ createTestMetdataRepository(new IInstallableUnit[] {sdk1, platform1, sdk2, platform2, egit1, egit2, egit3});
+
+ IProfileChangeRequest originalRequest = planner.createChangeRequest(profile);
+ originalRequest.add(egit2);
+ originalRequest.setInstallableUnitInclusionRules(egit2, ProfileInclusionRules.createStrictInclusionRule(egit2));
+ originalRequest.remove(sdk1);
+
+ {
+ RequestFlexer av = new RequestFlexer(planner);
+ av.setProvisioningContext(context);
+ IProfileChangeRequest realRequest = av.getChangeRequest(originalRequest, profile, new NullProgressMonitor());
+ assertTrue(realRequest.getAdditions().contains(egit2));
+ assertTrue(realRequest.getRemovals().contains(sdk1));
+ assertEquals(1, realRequest.getAdditions().size());
+ assertResolve(realRequest, planner);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.ui.sdk/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.ui.sdk/META-INF/MANIFEST.MF
index 0cea352..028ac3a 100644
--- a/bundles/org.eclipse.equinox.p2.ui.sdk/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.ui.sdk/META-INF/MANIFEST.MF
@@ -19,6 +19,7 @@ Import-Package: javax.xml.parsers,
org.eclipse.equinox.p2.engine.query;version="[2.0.0,3.0.0)",
org.eclipse.equinox.p2.metadata;version="[2.0.0,3.0.0)",
org.eclipse.equinox.p2.operations;version="[2.0.0,3.0.0)",
+ org.eclipse.equinox.p2.planner;version="2.0.0",
org.eclipse.equinox.p2.query;version="[2.0.0,3.0.0)",
org.eclipse.osgi.util;version="1.1.0",
org.osgi.framework;version="1.6.0",
diff --git a/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/UpdateHandler.java b/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/UpdateHandler.java
index f2ce43a..a416a17 100644
--- a/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/UpdateHandler.java
+++ b/bundles/org.eclipse.equinox.p2.ui.sdk/src/org/eclipse/equinox/internal/p2/ui/sdk/UpdateHandler.java
@@ -11,10 +11,13 @@
package org.eclipse.equinox.internal.p2.ui.sdk;
import org.eclipse.core.runtime.*;
-import org.eclipse.equinox.p2.operations.RepositoryTracker;
-import org.eclipse.equinox.p2.operations.UpdateOperation;
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;
+import org.eclipse.core.runtime.jobs.JobChangeAdapter;
+import org.eclipse.equinox.p2.operations.*;
import org.eclipse.equinox.p2.ui.LoadMetadataRepositoryJob;
import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.statushandlers.StatusManager;
/**
* UpdateHandler invokes the check for updates UI
@@ -39,7 +42,33 @@ public class UpdateHandler extends PreloadingRepositoryHandler {
// Report any missing repositories.
job.reportAccumulatedStatus();
if (getProvisioningUI().getPolicy().continueWorkingWithOperation(operation, getShell())) {
- getProvisioningUI().openUpdateWizard(false, operation, job);
+
+ if (operation.getResolutionResult() == Status.OK_STATUS) {
+ getProvisioningUI().openUpdateWizard(false, operation, job);
+ } else {
+
+ final RemediationOperation remediationOperation = new RemediationOperation(getProvisioningUI().getSession(), operation.getProfileChangeRequest(), true);
+ ProvisioningJob job2 = new ProvisioningJob("Searching alternate solutions...", getProvisioningUI().getSession()) {
+ @Override
+ public IStatus runModal(IProgressMonitor monitor) {
+ monitor.beginTask("Some items cannot be at the highest version. Searching for the highest common denominator ...", RemedyConfig.getAllRemdyConfigs().length);
+ return remediationOperation.resolveModal(monitor);
+ }
+ };
+ job2.addJobChangeListener(new JobChangeAdapter() {
+ public void done(IJobChangeEvent event) {
+ if (PlatformUI.isWorkbenchRunning()) {
+ PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ getProvisioningUI().openUpdateWizard(true, operation, remediationOperation, null);
+ }
+ });
+ }
+ }
+
+ });
+ getProvisioningUI().schedule(job2, StatusManager.SHOW | StatusManager.LOG);
+ }
}
}
diff --git a/bundles/org.eclipse.equinox.p2.ui/icons/obj/iu_add.gif b/bundles/org.eclipse.equinox.p2.ui/icons/obj/iu_add.gif
new file mode 100644
index 0000000..252d7eb
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.ui/icons/obj/iu_add.gif
Binary files differ
diff --git a/bundles/org.eclipse.equinox.p2.ui/icons/obj/iu_remove.gif b/bundles/org.eclipse.equinox.p2.ui/icons/obj/iu_remove.gif
new file mode 100644
index 0000000..b6922ac
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.ui/icons/obj/iu_remove.gif
Binary files differ
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIActivator.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIActivator.java
index 6341f41..b1dbad8 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIActivator.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIActivator.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2011 IBM Corporation and others.
+ * Copyright (c) 2007, 2013 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
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Red Hat, Inc. - support for remediation page
*******************************************************************************/
package org.eclipse.equinox.internal.p2.ui;
@@ -108,6 +109,8 @@ public class ProvUIActivator extends AbstractUIPlugin {
createImageDescriptor(ProvUIImages.IMG_IU, reg);
createImageDescriptor(ProvUIImages.IMG_DISABLED_IU, reg);
createImageDescriptor(ProvUIImages.IMG_UPDATED_IU, reg);
+ createImageDescriptor(ProvUIImages.IMG_ADDED_IU, reg);
+ createImageDescriptor(ProvUIImages.IMG_REMOVED_IU, reg);
createImageDescriptor(ProvUIImages.IMG_PATCH_IU, reg);
createImageDescriptor(ProvUIImages.IMG_DISABLED_PATCH_IU, reg);
createImageDescriptor(ProvUIImages.IMG_CATEGORY, reg);
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIImages.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIImages.java
index 050ce6b..c68aafb 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIImages.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIImages.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2011 IBM Corporation and others.
+ * Copyright (c) 2007, 2013 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
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Red Hat, Inc. - support for remediation page
*******************************************************************************/
package org.eclipse.equinox.internal.p2.ui;
@@ -39,6 +40,8 @@ public class ProvUIImages {
public final static String IMG_IU = "obj/iu_obj.gif"; //$NON-NLS-1$
public final static String IMG_DISABLED_IU = "obj/iu_disabled_obj.gif"; //$NON-NLS-1$
public final static String IMG_UPDATED_IU = "obj/iu_update_obj.gif"; //$NON-NLS-1$
+ public final static String IMG_ADDED_IU = "obj/iu_add.gif"; //$NON-NLS-1$
+ public final static String IMG_REMOVED_IU = "obj/iu_remove.gif"; //$NON-NLS-1$
public final static String IMG_PATCH_IU = "obj/iu_patch_obj.gif"; //$NON-NLS-1$
public final static String IMG_DISABLED_PATCH_IU = "obj/iu_disabled_patch_obj.gif"; //$NON-NLS-1$
public final static String IMG_PROFILE = "obj/profile_obj.gif"; //$NON-NLS-1$
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIMessages.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIMessages.java
index bb0b3d9..70defec 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIMessages.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/ProvUIMessages.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2011 IBM Corporation and others.
+ * Copyright (c) 2007, 2013 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
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Red Hat, Inc - support for remediation page
*******************************************************************************/
package org.eclipse.equinox.internal.p2.ui;
@@ -234,6 +235,21 @@ public class ProvUIMessages extends NLS {
public static String RollbackProfileElement_CurrentInstallation;
public static String SelectableIUsPage_Select_All;
public static String SelectableIUsPage_Deselect_All;
+ public static String InstallRemediationPage_Title;
+ public static String InstallRemediationPage_Description;
+ public static String UpdateRemediationPage_Title;
+ public static String UpdateRemediationPage_Description;
+ public static String RemediationPage_SubDescription;
+ public static String RemediationPage_NoSolutionFound;
+ public static String RemediationPage_BeingInstalledSection;
+ public static String RemediationPage_InstalledSection;
+ public static String RemediationPage_BeingInstalledSection_AllowPartialInstall;
+ public static String RemediationPage_BeingInstalledSection_AllowDifferentVersion;
+ public static String RemediationPage_InstalledSection_AllowInstalledUpdate;
+ public static String RemediationPage_InstalledSection_AllowInstalledRemoval;
+ public static String RemediationPage_BestSolutionBeingInstalledRelaxed;
+ public static String RemediationPage_BestSolutionInstallationRelaxed;
+ public static String RemediationPage_BestSolutionBuilt;
public static String TrustCertificateDialog_Details;
public static String TrustCertificateDialog_Title;
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/ProfileModificationAction.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/ProfileModificationAction.java
index 31d2fa5..1380cbc 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/ProfileModificationAction.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/ProfileModificationAction.java
@@ -91,7 +91,8 @@ public abstract class ProfileModificationAction extends ProvisioningAction {
}
});
- getProvisioningUI().schedule(job, StatusManager.SHOW | StatusManager.LOG);
+ // Don't show the error dialog anymore since the remediation operation should be computed
+ getProvisioningUI().schedule(job, StatusManager.NONE | StatusManager.LOG);
}
// Since we are resolving asynchronously, our job is done. Setting this allows
// callers to decide to close the launching window.
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/UpdateAction.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/UpdateAction.java
index 289c523..2fcc0f0 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/UpdateAction.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/actions/UpdateAction.java
@@ -14,15 +14,20 @@ package org.eclipse.equinox.internal.p2.ui.actions;
import java.util.ArrayList;
import java.util.Collection;
+import org.eclipse.core.runtime.*;
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;
+import org.eclipse.core.runtime.jobs.JobChangeAdapter;
+import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
import org.eclipse.equinox.internal.p2.ui.ProvUI;
import org.eclipse.equinox.internal.p2.ui.ProvUIMessages;
import org.eclipse.equinox.internal.p2.ui.model.IUElementListRoot;
import org.eclipse.equinox.p2.engine.IProfile;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
-import org.eclipse.equinox.p2.operations.ProfileChangeOperation;
-import org.eclipse.equinox.p2.operations.UpdateOperation;
+import org.eclipse.equinox.p2.operations.*;
import org.eclipse.equinox.p2.ui.ProvisioningUI;
import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.statushandlers.StatusManager;
public class UpdateAction extends ExistingIUInProfileAction {
@@ -66,7 +71,41 @@ public class UpdateAction extends ExistingIUInProfileAction {
/* (non-Javadoc)
* @see org.eclipse.equinox.internal.p2.ui.actions.ProfileModificationAction#performAction(org.eclipse.equinox.p2.operations.ProfileChangeOperation, org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit[])
*/
- protected int performAction(ProfileChangeOperation operation, Collection<IInstallableUnit> ius) {
- return ui.openUpdateWizard(skipSelectionPage, (UpdateOperation) operation, null);
+ protected int performAction(final ProfileChangeOperation operation, Collection<IInstallableUnit> ius) {
+ if (operation.getResolutionResult() == Status.OK_STATUS)
+ return ui.openUpdateWizard(skipSelectionPage, (UpdateOperation) operation, null);
+
+ final RemediationOperation remediationOperation = new RemediationOperation(getSession(), (ProfileChangeRequest) operation.getProfileChangeRequest());
+ ProvisioningJob job = new ProvisioningJob("Searching alternate solutions...", getSession()) {
+ @Override
+ public IStatus runModal(IProgressMonitor monitor) {
+ monitor.beginTask("The update operation cannot be completed as requested. Searching alternate solutions ...", RemedyConfig.getAllRemdyConfigs().length);
+ return remediationOperation.resolveModal(monitor);
+ }
+ };
+ job.addJobChangeListener(new JobChangeAdapter() {
+ public void done(IJobChangeEvent event) {
+ if (PlatformUI.isWorkbenchRunning()) {
+ PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ ui.openUpdateWizard(skipSelectionPage, (UpdateOperation) operation, remediationOperation, null);
+ // UpdateWizard wizard = new UpdateWizard(ui, (UpdateOperation) operation, ((UpdateOperation) operation).getSelectedUpdates(), null);
+ // wizard.setSkipSelectionsPage(skipSelectionPage);
+ // wizard.setRemediationOperation(remediationOperation);
+ // WizardDialog dialog = new ProvisioningWizardDialog(ProvUI.getDefaultParentShell(), wizard);
+ // dialog.create();
+ // PlatformUI.getWorkbench().getHelpSystem().setHelp(dialog.getShell(), IProvHelpContextIds.UPDATE_WIZARD);
+ // if (wizard.getCurrentStatus().getSeverity() == IStatus.ERROR) {
+ // wizard.deselectLockedIUs();
+ // }
+ // dialog.open();
+ }
+ });
+ }
+ }
+
+ });
+ getProvisioningUI().schedule(job, StatusManager.SHOW | StatusManager.LOG);
+ return 1;
}
}
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstallWizard.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstallWizard.java
index 142b788..57949d8 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstallWizard.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstallWizard.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2010 IBM Corporation and others.
+ * Copyright (c) 2007, 2013 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
@@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Sonatype, Inc. - ongoing development
+ * Red Hat, Inc. - support for remediation page
*******************************************************************************/
package org.eclipse.equinox.internal.p2.ui.dialogs;
@@ -18,8 +19,7 @@ import org.eclipse.equinox.internal.p2.ui.*;
import org.eclipse.equinox.internal.p2.ui.model.*;
import org.eclipse.equinox.p2.engine.ProvisioningContext;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
-import org.eclipse.equinox.p2.operations.InstallOperation;
-import org.eclipse.equinox.p2.operations.ProfileChangeOperation;
+import org.eclipse.equinox.p2.operations.*;
import org.eclipse.equinox.p2.ui.LoadMetadataRepositoryJob;
import org.eclipse.equinox.p2.ui.ProvisioningUI;
import org.eclipse.jface.dialogs.IDialogConstants;
@@ -64,18 +64,24 @@ public class InstallWizard extends WizardWithLicenses {
if (selectedElements == null)
return;
root = new IUElementListRoot();
- ArrayList<AvailableIUElement> list = new ArrayList<AvailableIUElement>(selectedElements.length);
- ArrayList<AvailableIUElement> selections = new ArrayList<AvailableIUElement>(selectedElements.length);
- for (int i = 0; i < selectedElements.length; i++) {
- IInstallableUnit iu = ElementUtils.getIU(selectedElements[i]);
- if (iu != null) {
- AvailableIUElement element = new AvailableIUElement(root, iu, getProfileId(), shouldShowProvisioningPlanChildren());
- list.add(element);
- selections.add(element);
+ if (operation instanceof RemediationOperation) {
+ ArrayList<AvailableIUElement> list = remediationPage.transformIUstoIUElements();
+ root.setChildren(list.toArray());
+ planSelections = list.toArray();
+ } else {
+ ArrayList<AvailableIUElement> list = new ArrayList<AvailableIUElement>(selectedElements.length);
+ ArrayList<AvailableIUElement> selections = new ArrayList<AvailableIUElement>(selectedElements.length);
+ for (int i = 0; i < selectedElements.length; i++) {
+ IInstallableUnit iu = ElementUtils.getIU(selectedElements[i]);
+ if (iu != null) {
+ AvailableIUElement element = new AvailableIUElement(root, iu, getProfileId(), shouldShowProvisioningPlanChildren());
+ list.add(element);
+ selections.add(element);
+ }
}
+ root.setChildren(list.toArray());
+ planSelections = selections.toArray();
}
- root.setChildren(list.toArray());
- planSelections = selections.toArray();
}
/*
@@ -116,6 +122,11 @@ public class InstallWizard extends WizardWithLicenses {
return errorReportingPage;
}
+ protected RemediationPage createRemediationPage() {
+ remediationPage = new RemediationPage(ui, this, root, operation);
+ return remediationPage;
+ }
+
/* (non-Javadoc)
* @see org.eclipse.equinox.internal.p2.ui.dialogs.ProvisioningOperationWizard#getProfileChangeOperation(java.lang.Object[])
*/
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstallWizardPage.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstallWizardPage.java
index d50b2f6..b4f3bc5 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstallWizardPage.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/InstallWizardPage.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2010 IBM Corporation and others.
+ * Copyright (c) 2007, 2013 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
@@ -7,17 +7,18 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Red Hat, Inc. - support for remediation page
*******************************************************************************/
package org.eclipse.equinox.internal.p2.ui.dialogs;
import org.eclipse.equinox.internal.p2.ui.ProvUIMessages;
import org.eclipse.equinox.internal.p2.ui.model.IUElementListRoot;
-import org.eclipse.equinox.p2.operations.InstallOperation;
+import org.eclipse.equinox.p2.operations.ProfileChangeOperation;
import org.eclipse.equinox.p2.ui.ProvisioningUI;
public class InstallWizardPage extends SizeComputingWizardPage {
- public InstallWizardPage(ProvisioningUI ui, ProvisioningOperationWizard wizard, IUElementListRoot root, InstallOperation operation) {
+ public InstallWizardPage(ProvisioningUI ui, ProvisioningOperationWizard wizard, IUElementListRoot root, ProfileChangeOperation operation) {
super(ui, wizard, root, operation);
setTitle(ProvUIMessages.InstallWizardPage_Title);
setDescription(ProvUIMessages.InstallWizardPage_NoCheckboxDescription);
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/PreselectedIUInstallWizard.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/PreselectedIUInstallWizard.java
index aa77d00..7d45188 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/PreselectedIUInstallWizard.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/PreselectedIUInstallWizard.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009, 2011 IBM Corporation and others.
+ * Copyright (c) 2009, 2013 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
@@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Sonatype, Inc. - ongoing development
+ * Red Hat, Inc. - support for remediation page
*******************************************************************************/
package org.eclipse.equinox.internal.p2.ui.dialogs;
@@ -84,4 +85,11 @@ public class PreselectedIUInstallWizard extends WizardWithLicenses {
// op.setRootMarkerKey(getRootMarkerKey());
return op;
}
+
+ @Override
+ protected RemediationPage createRemediationPage() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
}
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ProvisioningOperationWizard.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ProvisioningOperationWizard.java
index efe2f3f..6df089c 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ProvisioningOperationWizard.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ProvisioningOperationWizard.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2008, 2011 IBM Corporation and others.
+ * Copyright (c) 2008, 2013 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
@@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Sonatype, Inc. - ongoing development
+ * Red Hat, Inc. - support for remediation page
*******************************************************************************/
package org.eclipse.equinox.internal.p2.ui.dialogs;
@@ -15,12 +16,13 @@ import java.lang.reflect.InvocationTargetException;
import java.util.HashSet;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.*;
+import org.eclipse.equinox.internal.p2.director.ProfileChangeRequest;
import org.eclipse.equinox.internal.p2.ui.*;
import org.eclipse.equinox.internal.p2.ui.model.ElementUtils;
import org.eclipse.equinox.internal.p2.ui.model.IUElementListRoot;
import org.eclipse.equinox.p2.engine.ProvisioningContext;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
-import org.eclipse.equinox.p2.operations.ProfileChangeOperation;
+import org.eclipse.equinox.p2.operations.*;
import org.eclipse.equinox.p2.ui.*;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
@@ -38,11 +40,11 @@ import org.eclipse.ui.statushandlers.StatusManager;
public abstract class ProvisioningOperationWizard extends Wizard {
private static final String WIZARD_SETTINGS_SECTION = "WizardSettings"; //$NON-NLS-1$
-
protected ProvisioningUI ui;
protected IUElementListRoot root;
protected ProfileChangeOperation operation;
protected Object[] planSelections;
+ protected RemediationPage remediationPage;
protected ISelectableIUsPage mainPage;
protected IResolutionErrorReportingPage errorPage;
protected ResolutionResultsWizardPage resolutionPage;
@@ -50,8 +52,8 @@ public abstract class ProvisioningOperationWizard extends Wizard {
protected LoadMetadataRepositoryJob repoPreloadJob;
IStatus couldNotResolveStatus = Status.OK_STATUS; // we haven't tried and failed
boolean resolveWithRelaxedConstraints = false;
-
boolean waitingForOtherJobs = false;
+ protected RemediationOperation remediationOperation;
public ProvisioningOperationWizard(ProvisioningUI ui, ProfileChangeOperation operation, Object[] initialSelections, LoadMetadataRepositoryJob job) {
super();
@@ -66,6 +68,14 @@ public abstract class ProvisioningOperationWizard extends Wizard {
}
}
+ public void setRemediationOperation(RemediationOperation remediationOperation) {
+ this.remediationOperation = remediationOperation;
+ }
+
+ public RemediationOperation getRemediationOperation() {
+ return remediationOperation;
+ }
+
/*
* (non-Javadoc)
* @see org.eclipse.jface.wizard.Wizard#addPages()
@@ -76,10 +86,15 @@ public abstract class ProvisioningOperationWizard extends Wizard {
errorPage = createErrorReportingPage();
if (errorPage != mainPage)
addPage(errorPage);
+ remediationPage = createRemediationPage();
+ if (remediationPage != null)
+ addPage(remediationPage);
resolutionPage = createResolutionPage();
addPage(resolutionPage);
}
+ protected abstract RemediationPage createRemediationPage();
+
protected abstract IResolutionErrorReportingPage createErrorReportingPage();
protected abstract ISelectableIUsPage createMainPage(IUElementListRoot input, Object[] selections);
@@ -96,16 +111,48 @@ public abstract class ProvisioningOperationWizard extends Wizard {
/*
* (non-Javadoc)
+ * @see org.eclipse.jface.wizard.Wizard#getPreviousPage(org.eclipse.jface.wizard.IWizardPage)
+ *
+ */
+ public IWizardPage getPreviousPage(IWizardPage page) {
+ if (page == errorPage) {
+ return mainPage;
+ }
+ return super.getPreviousPage(page);
+ }
+
+ /*
+ * (non-Javadoc)
* @see org.eclipse.jface.wizard.Wizard#getNextPage(org.eclipse.jface.wizard.IWizardPage)
+ *
*/
public IWizardPage getNextPage(IWizardPage page) {
// If we are moving from the main page or error page, we may need to resolve before
// advancing.
- if (page == mainPage || page == errorPage) {
+
+ if (page == remediationPage) {
+ remediationOperation.setSelectedRemedy(remediationPage.getSelectedRemedy());
+ try {
+ getContainer().run(true, false, new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) {
+ remediationOperation.resolveModal(monitor);
+ }
+ });
+ } catch (InterruptedException e) {
+ // Nothing to report if thread was interrupted
+ } catch (InvocationTargetException e) {
+ ProvUI.handleException(e.getCause(), null, StatusManager.SHOW | StatusManager.LOG);
+ couldNotResolve(null);
+ }
+ operation = remediationOperation;
+ initializeResolutionModelElements(remediationPage.transformIUstoIUElements().toArray());
+ planChanged();
+ return resolutionPage;
+ } else if (page == mainPage || page == errorPage) {
ISelectableIUsPage currentPage = (ISelectableIUsPage) page;
// Do we need to resolve?
if (operation == null || (operation != null && shouldRecomputePlan(currentPage))) {
- recomputePlan(getContainer());
+ recomputePlan(getContainer(), true);
} else {
// the selections have not changed from an IU point of view, but we want
// to reinitialize the resolution model elements to ensure they are up to
@@ -114,10 +161,22 @@ public abstract class ProvisioningOperationWizard extends Wizard {
}
IStatus status = operation.getResolutionResult();
if (status == null || status.getSeverity() == IStatus.ERROR) {
- return errorPage;
+ if (page == mainPage) {
+ if (remediationOperation != null && remediationOperation.hasRemedies() && remediationOperation.getRemedies().size() == 1) {
+ planChanged();
+ remediationPage.setSelectedRemedy(remediationOperation.getRemedies().get(0));
+ return getNextPage(remediationPage);
+ } else if (remediationOperation != null && remediationOperation.hasRemedies()) {
+ planChanged();
+ return remediationPage;
+ }
+ return errorPage;
+ }
} else if (status.getSeverity() == IStatus.CANCEL) {
return page;
} else {
+ if (remediationPage != null)
+ remediationPage.setPageComplete(true);
return resolutionPage;
}
}
@@ -172,6 +231,10 @@ public abstract class ProvisioningOperationWizard extends Wizard {
}
protected void planChanged() {
+ IWizardPage currentPage = ((WizardDialog) getContainer()).getCurrentPage();
+ if ((currentPage == null || currentPage == mainPage) && remediationPage != null && remediationOperation != null && remediationOperation.hasRemedies()) {
+ remediationPage.updateStatus(root, operation, planSelections);
+ }
resolutionPage.updateStatus(root, operation);
if (errorPage != resolutionPage) {
IUElementListRoot newRoot = shouldUpdateErrorPageModelOnPlanChange() ? root : null;
@@ -192,31 +255,16 @@ public abstract class ProvisioningOperationWizard extends Wizard {
return new ProvisioningContext(ui.getSession().getProvisioningAgent());
}
- public void recomputePlanWithRelaxedConstraints(IRunnableContext runnableContext) {
- couldNotResolveStatus = Status.OK_STATUS;
- provisioningContext = getProvisioningContext();
- initializeResolutionModelElements(getOperationSelections());
- if (planSelections.length == 0) {
- operation = null;
- couldNotResolve(ProvUIMessages.ResolutionWizardPage_NoSelections);
- } else {
- operation = ui.getRelaxedUpdateOperation(provisioningContext);
- operation.setProvisioningContext(provisioningContext);
- try {
- runnableContext.run(true, true, new IRunnableWithProgress() {
- public void run(IProgressMonitor monitor) {
- operation.resolveModal(monitor);
- }
- });
+ public void recomputePlan(IRunnableContext runnableContext) {
+ recomputePlan(runnableContext, false);
+ }
- } catch (InterruptedException e) {
- // Nothing to report if thread was interrupted
- } catch (InvocationTargetException e) {
- ProvUI.handleException(e.getCause(), null, StatusManager.SHOW | StatusManager.LOG);
- couldNotResolve(null);
- }
- }
- planChanged();
+ public void computeRemediationOperation(ProfileChangeOperation operation, ProvisioningUI ui, IProgressMonitor monitor) {
+ SubMonitor sub = SubMonitor.convert(monitor, "remediationoperation", RemedyConfig.getAllRemdyConfigs().length);
+ monitor.setTaskName("compute remediation operation");
+ remediationOperation = new RemediationOperation(ui.getSession(), (ProfileChangeRequest) operation.getProfileChangeRequest());
+ remediationOperation.getResolveJob(monitor);
+ sub.done();
}
/**
@@ -225,11 +273,7 @@ public abstract class ProvisioningOperationWizard extends Wizard {
*
* @param runnableContext
*/
- public void recomputePlan(IRunnableContext runnableContext) {
- if (resolveWithRelaxedConstraints) {
- recomputePlanWithRelaxedConstraints(runnableContext);
- return;
- }
+ public void recomputePlan(IRunnableContext runnableContext, final boolean withRemediation) {
couldNotResolveStatus = Status.OK_STATUS;
provisioningContext = getProvisioningContext();
initializeResolutionModelElements(getOperationSelections());
@@ -243,9 +287,14 @@ public abstract class ProvisioningOperationWizard extends Wizard {
runnableContext.run(true, true, new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) {
operation.resolveModal(monitor);
+ if (withRemediation) {
+ IStatus status = operation.getResolutionResult();
+ if (remediationPage != null && (status == null || (status.getSeverity() == IStatus.ERROR && status.getCode() != 10053))) {
+ computeRemediationOperation(operation, ui, monitor);
+ }
+ }
}
});
-
} catch (InterruptedException e) {
// Nothing to report if thread was interrupted
} catch (InvocationTargetException e) {
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/RemediationPage.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/RemediationPage.java
new file mode 100644
index 0000000..e979293
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/RemediationPage.java
@@ -0,0 +1,343 @@
+package org.eclipse.equinox.internal.p2.ui.dialogs;
+
+import java.util.*;
+import java.util.List;
+import org.eclipse.equinox.internal.p2.ui.ProvUIMessages;
+import org.eclipse.equinox.internal.p2.ui.model.*;
+import org.eclipse.equinox.internal.p2.ui.viewers.*;
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.operations.*;
+import org.eclipse.equinox.p2.ui.ProvisioningUI;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.custom.StackLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.*;
+
+public class RemediationPage extends ResolutionStatusPage {
+ private static final int ALLOWPARTIALINSTALL_INDEX = 0;
+ private static final int ALLOWDIFFERENTVERSION_INDEX = 1;
+ private static final int ALLOWINSTALLEDUPDATE_INDEX = 2;
+ private static final int ALLOWINSTALLEDREMOVAL_INDEX = 3;
+ private static final HashMap<String, String[]> CONSTRAINTS = new HashMap<String, String[]>() {
+ {
+ put(ProvUIMessages.RemediationPage_BeingInstalledSection, new String[] {ProvUIMessages.RemediationPage_BeingInstalledSection_AllowPartialInstall, ProvUIMessages.RemediationPage_BeingInstalledSection_AllowDifferentVersion});
+ put(ProvUIMessages.RemediationPage_InstalledSection, new String[] {ProvUIMessages.RemediationPage_InstalledSection_AllowInstalledUpdate, ProvUIMessages.RemediationPage_InstalledSection_AllowInstalledRemoval});
+ }
+ };
+
+ private Composite mainComposite;
+ private Composite resultComposite;
+ private Composite resultNotFoundComposite;
+ private Composite resultErrorComposite;
+ private StackLayout switchResultLayout;
+ private Composite resultFoundComposite;
+ protected IUElementListRoot input;
+ private TreeViewer treeViewer;
+ private Remedy selectedRemedy;
+
+ private IUDetailsGroup iuDetailsGroup;
+ private Listener bestSolutionlistener;
+ private Button bestBeingInstalledRelaxedButton;
+ private Button bestInstalledRelaxedButton;
+ private Button buildMyOwnSolution;
+ private ArrayList<Button> checkboxes;
+
+ protected RemediationPage(ProvisioningUI ui, ProvisioningOperationWizard wizard, IUElementListRoot input, ProfileChangeOperation operation) {
+ super("RemediationPage", ui, wizard); //$NON-NLS-1$
+ if (getWizard() instanceof UpdateWizard) {
+ setTitle(ProvUIMessages.InstallRemediationPage_Title);
+ setDescription(ProvUIMessages.InstallRemediationPage_Description);
+ } else {
+ setTitle(ProvUIMessages.UpdateRemediationPage_Title);
+ setDescription(ProvUIMessages.UpdateRemediationPage_Description);
+ }
+ }
+
+ public void createControl(Composite parent) {
+ mainComposite = new Composite(parent, SWT.NONE);
+ checkboxes = new ArrayList<Button>();
+ mainComposite.setLayout(new GridLayout());
+
+ Label descriptionLabel = new Label(mainComposite, SWT.NONE);
+ descriptionLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+ descriptionLabel.setText(ProvUIMessages.RemediationPage_SubDescription);
+
+ bestSolutionlistener = new Listener() {
+ public void handleEvent(Event e) {
+ Button btn = (Button) e.widget;
+ Remedy remedy = (btn.getData() == null ? null : (Remedy) btn.getData());
+ checkboxes.get(ALLOWPARTIALINSTALL_INDEX).setSelection(remedy != null && remedy.getConfig().allowPartialInstall);
+ checkboxes.get(ALLOWDIFFERENTVERSION_INDEX).setSelection(remedy != null && remedy.getConfig().allowDifferentVersion);
+ checkboxes.get(ALLOWINSTALLEDUPDATE_INDEX).setSelection(remedy != null && remedy.getConfig().allowInstalledUpdate);
+ checkboxes.get(ALLOWINSTALLEDREMOVAL_INDEX).setSelection(remedy != null && remedy.getConfig().allowInstalledRemoval);
+ for (Iterator<Button> iterator = checkboxes.iterator(); iterator.hasNext();) {
+ Button btn1 = iterator.next();
+ btn1.setEnabled(remedy == null);
+ }
+ refreshResultComposite();
+ }
+ };
+
+ bestBeingInstalledRelaxedButton = new Button(mainComposite, SWT.RADIO);
+ bestBeingInstalledRelaxedButton.setText(ProvUIMessages.RemediationPage_BestSolutionBeingInstalledRelaxed);
+ bestBeingInstalledRelaxedButton.addListener(SWT.Selection, bestSolutionlistener);
+
+ bestInstalledRelaxedButton = new Button(mainComposite, SWT.RADIO);
+ bestInstalledRelaxedButton.setText(ProvUIMessages.RemediationPage_BestSolutionInstallationRelaxed);
+ bestInstalledRelaxedButton.addListener(SWT.Selection, bestSolutionlistener);
+
+ buildMyOwnSolution = new Button(mainComposite, SWT.RADIO);
+ buildMyOwnSolution.setText(ProvUIMessages.RemediationPage_BestSolutionBuilt);
+ buildMyOwnSolution.addListener(SWT.Selection, bestSolutionlistener);
+
+ Listener relaxedConstraintlistener = new Listener() {
+ public void handleEvent(Event e) {
+ refreshResultComposite();
+ }
+ };
+
+ GridData gd = new GridData(SWT.FILL, SWT.FILL, true, false);
+ gd.horizontalIndent = 30;
+ Iterator<String> iter = CONSTRAINTS.keySet().iterator();
+ while (iter.hasNext()) {
+ String key = iter.next();
+ String[] values = CONSTRAINTS.get(key);
+ for (int i = 0; i < values.length; i++) {
+ Button checkBtn = new Button(mainComposite, SWT.CHECK);
+ checkBtn.setText(values[i]);
+ checkBtn.setData(values[i]);
+ checkBtn.setLayoutData(gd);
+ checkBtn.addListener(SWT.Selection, relaxedConstraintlistener);
+ checkboxes.add(checkBtn);
+ }
+
+ }
+
+ resultComposite = new Composite(mainComposite, SWT.NONE);
+ switchResultLayout = new StackLayout();
+ resultComposite.setLayout(switchResultLayout);
+ GridData data = new GridData(GridData.FILL_BOTH);
+ resultComposite.setLayoutData(data);
+
+ resultErrorComposite = new Composite(resultComposite, SWT.NONE);
+ resultErrorComposite.setLayout(new GridLayout());
+
+ resultNotFoundComposite = new Composite(resultComposite, SWT.NONE);
+ resultNotFoundComposite.setLayout(new GridLayout());
+ Label resultNotFoundLabel = new Label(resultNotFoundComposite, SWT.NONE);
+ resultNotFoundLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+ resultNotFoundLabel.setText(ProvUIMessages.RemediationPage_NoSolutionFound);
+
+ resultFoundComposite = new Composite(resultComposite, SWT.NONE);
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.marginWidth = 0;
+ gridLayout.marginHeight = 0;
+ resultFoundComposite.setLayout(gridLayout);
+
+ treeViewer = new TreeViewer(resultFoundComposite, SWT.BORDER | SWT.MULTI | SWT.FULL_SELECTION);
+ data = new GridData(GridData.FILL_BOTH);
+ data.heightHint = convertHeightInCharsToPixels(ILayoutConstants.DEFAULT_TABLE_HEIGHT);
+ data.widthHint = convertWidthInCharsToPixels(ILayoutConstants.DEFAULT_TABLE_WIDTH);
+ Tree tree = treeViewer.getTree();
+ tree.setLayoutData(data);
+ tree.setHeaderVisible(true);
+ activateCopy(tree);
+ IUColumnConfig[] columns = getColumnConfig();
+ for (int i = 0; i < columns.length; i++) {
+ TreeColumn tc = new TreeColumn(tree, SWT.LEFT, i);
+ tc.setResizable(true);
+ tc.setText(columns[i].getColumnTitle());
+ tc.setWidth(columns[i].getWidthInPixels(tree));
+ }
+
+ // Filters and sorters before establishing content, so we don't refresh unnecessarily.
+ IUComparator comparator = new IUComparator(IUComparator.IU_NAME);
+ comparator.useColumnConfig(getColumnConfig());
+ treeViewer.setComparator(comparator);
+ treeViewer.setComparer(new ProvElementComparer());
+
+ ProvElementContentProvider contentProvider = new ProvElementContentProvider();
+ treeViewer.setContentProvider(contentProvider);
+ IUDetailsLabelProvider labelProvider = new IUDetailsLabelProvider(null, getColumnConfig(), getShell());
+ treeViewer.setLabelProvider(labelProvider);
+ resultComposite.setVisible(false);
+ iuDetailsGroup = new IUDetailsGroup(resultErrorComposite, treeViewer, convertWidthInCharsToPixels(ILayoutConstants.DEFAULT_TABLE_WIDTH), true);
+
+ setControl(mainComposite);
+ setPageComplete(false);
+
+ Dialog.applyDialogFont(mainComposite);
+
+ }
+
+ public boolean canFlipToNextPage() {
+ return isPageComplete();
+ }
+
+ public void updateStatus(IUElementListRoot newRoot, ProfileChangeOperation operation, Object[] planSelections) {
+ setDetailText(operation);
+ checkboxes.get(ALLOWPARTIALINSTALL_INDEX).setEnabled(planSelections.length > 1);
+ RemediationOperation remediationOperation = ((ProvisioningOperationWizard) getWizard()).getRemediationOperation();
+ boolean isSelected = false;
+ if (remediationOperation.bestSolutionChangingTheRequest() != null) {
+ bestBeingInstalledRelaxedButton.setData(remediationOperation.bestSolutionChangingTheRequest());
+ bestBeingInstalledRelaxedButton.setSelection(true);
+ bestBeingInstalledRelaxedButton.notifyListeners(SWT.Selection, new Event());
+ isSelected = true;
+ }
+ bestBeingInstalledRelaxedButton.setEnabled(remediationOperation.bestSolutionChangingTheRequest() != null);
+
+ if (remediationOperation.bestSolutionChangingWhatIsInstalled() != null) {
+ bestInstalledRelaxedButton.setData(remediationOperation.bestSolutionChangingWhatIsInstalled());
+ bestInstalledRelaxedButton.setSelection(isSelected == false);
+ if (!isSelected)
+ bestInstalledRelaxedButton.notifyListeners(SWT.Selection, new Event());
+ isSelected = true;
+ }
+ bestInstalledRelaxedButton.setEnabled(remediationOperation.bestSolutionChangingWhatIsInstalled() != null);
+ buildMyOwnSolution.setSelection(isSelected == false);
+ if (!isSelected)
+ buildMyOwnSolution.notifyListeners(SWT.Selection, new Event());
+ }
+
+ @Override
+ protected void updateCaches(IUElementListRoot root, ProfileChangeOperation resolvedOperation) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected boolean isCreated() {
+ return false;
+ }
+
+ @Override
+ protected IUDetailsGroup getDetailsGroup() {
+ return iuDetailsGroup;
+ }
+
+ @Override
+ protected IInstallableUnit getSelectedIU() {
+ // Not applicable
+ return null;
+ }
+
+ @Override
+ protected Object[] getSelectedElements() {
+ return new Object[] {};//((ProvisioningOperationWizard) getWizard()).mainPage.getSelectedIUElements();
+ }
+
+ public ArrayList<AvailableIUElement> transformIUstoIUElements() {
+ ArrayList<AvailableIUElement> temp = new ArrayList<AvailableIUElement>();
+ ArrayList<String> updateIds = new ArrayList<String>();
+ IUElementListRoot root = new IUElementListRoot();
+ for (IInstallableUnit addedIU : selectedRemedy.getRequest().getAdditions()) {
+ AvailableIUElement element = new AvailableIUElement(root, addedIU, getProfileId(), true);
+ for (IInstallableUnit removedIU : selectedRemedy.getRequest().getRemovals()) {
+ if (removedIU.getId().equals(addedIU.getId())) {
+ //if (remediationOperation.isCheckForUpdates()) {
+ // for (IInstallableUnit originalUpdatedIU : remediationOperation.getOriginalRequest().getAdditions()) {
+ // int q = addedIU.getVersion().compareTo(originalUpdatedIU.getVersion());
+ //
+ // if (addedIU.getId() == originalUpdatedIU.getId() && addedIU.getVersion().compareTo(originalUpdatedIU.getVersion()) < 0) {
+ // }
+ // }
+ // }
+ element.setIsUpdate(true);
+ updateIds.add(addedIU.getId());
+ break;
+ }
+ }
+ temp.add(element);
+ }
+ for (IInstallableUnit removedIU : selectedRemedy.getRequest().getRemovals()) {
+ if (!updateIds.contains(removedIU.getId())) {
+ AvailableIUElement element = new AvailableIUElement(root, removedIU, getProfileId(), false);
+ element.setIsUninstall(true);
+ temp.add(element);
+ }
+ }
+ return temp;
+ }
+
+ private boolean isContraintOK(int btnIndex, boolean value) {
+ return (checkboxes.get(btnIndex).getSelection() && value) || (!checkboxes.get(btnIndex).getSelection() && !value);
+ }
+
+ public void refreshResultComposite() {
+ resultComposite.setVisible(true);
+ selectedRemedy = null;
+ if (!checkboxes.get(ALLOWPARTIALINSTALL_INDEX).getSelection() && !checkboxes.get(ALLOWDIFFERENTVERSION_INDEX).getSelection() && !checkboxes.get(ALLOWINSTALLEDUPDATE_INDEX).getSelection() && !checkboxes.get(ALLOWINSTALLEDREMOVAL_INDEX).getSelection()) {
+ switchResultLayout.topControl = resultErrorComposite;
+ } else {
+ RemediationOperation remediationOperation = ((ProvisioningOperationWizard) getWizard()).getRemediationOperation();
+ List<Remedy> remedies = remediationOperation.getRemedies();
+ for (Iterator<Remedy> iterator = remedies.iterator(); iterator.hasNext();) {
+ Remedy remedy = iterator.next();
+ if (isContraintOK(ALLOWPARTIALINSTALL_INDEX, remedy.getConfig().allowPartialInstall) && isContraintOK(ALLOWDIFFERENTVERSION_INDEX, remedy.getConfig().allowDifferentVersion) && isContraintOK(ALLOWINSTALLEDUPDATE_INDEX, remedy.getConfig().allowInstalledUpdate) && isContraintOK(ALLOWINSTALLEDREMOVAL_INDEX, remedy.getConfig().allowInstalledRemoval)) {
+ if (remedy.getRequest() != null) {
+ selectedRemedy = remedy;
+ break;
+ }
+ }
+ }
+ if (selectedRemedy == null) {
+ switchResultLayout.topControl = resultNotFoundComposite;
+ } else {
+ input = new IUElementListRoot();
+ ArrayList<AvailableIUElement> ius = new ArrayList<AvailableIUElement>();
+ ius.addAll(transformIUstoIUElements());
+ if (ius.size() == 0) {
+ switchResultLayout.topControl = resultNotFoundComposite;
+ selectedRemedy = null;
+ } else {
+ input.setChildren(ius.toArray());
+ treeViewer.setInput(input);
+ switchResultLayout.topControl = resultFoundComposite;
+ }
+ }
+ }
+ setPageComplete(selectedRemedy != null);
+ resultComposite.layout();
+ }
+
+ @Override
+ protected String getDialogSettingsName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected SashForm getSashForm() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ protected int getColumnWidth(int index) {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ protected String getClipboardText(Control control) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ protected Collection<IInstallableUnit> getIUs() {
+ return ElementUtils.elementsToIUs(input.getChildren(input));
+ }
+
+ public Remedy getSelectedRemedy() {
+ return selectedRemedy;
+ }
+
+ public void setSelectedRemedy(Remedy selectedRemedy) {
+ this.selectedRemedy = selectedRemedy;
+ }
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ResolutionResultsWizardPage.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ResolutionResultsWizardPage.java
index 8f823d6..e0f719e 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ResolutionResultsWizardPage.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/ResolutionResultsWizardPage.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2010 IBM Corporation and others.
+ * Copyright (c) 2007, 2013 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
@@ -9,13 +9,13 @@
* IBM Corporation - initial API and implementation
* EclipseSource - ongoing development
* Sonatype, Inc. - ongoing development
+ * Red Hat, Inc. - support for remediation page
*******************************************************************************/
package org.eclipse.equinox.internal.p2.ui.dialogs;
import java.util.Collection;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.ui.ProvUIActivator;
-import org.eclipse.equinox.internal.p2.ui.ProvUIMessages;
import org.eclipse.equinox.internal.p2.ui.model.*;
import org.eclipse.equinox.internal.p2.ui.viewers.*;
import org.eclipse.equinox.p2.engine.IProvisioningPlan;
@@ -30,8 +30,6 @@ import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.*;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.statushandlers.StatusManager;
@@ -55,7 +53,6 @@ public abstract class ResolutionResultsWizardPage extends ResolutionStatusPage {
protected Display display;
private IUDetailsGroup iuDetailsGroup;
SashForm sashForm;
- Button relaxConstraints;
protected ResolutionResultsWizardPage(ProvisioningUI ui, ProvisioningOperationWizard wizard, IUElementListRoot input, ProfileChangeOperation operation) {
super("ResolutionPage", ui, wizard); //$NON-NLS-1$
@@ -134,8 +131,6 @@ public abstract class ResolutionResultsWizardPage extends ResolutionStatusPage {
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, false);
controlsComposite.setLayoutData(gd);
- createViewControlsArea(controlsComposite);
-
final Runnable runnable = new Runnable() {
public void run() {
treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
@@ -167,31 +162,6 @@ public abstract class ResolutionResultsWizardPage extends ResolutionStatusPage {
@Override
public void updateStatus(IUElementListRoot newRoot, ProfileChangeOperation op) {
super.updateStatus(newRoot, op);
- IStatus currentStatus = getProvisioningWizard().getCurrentStatus();
- if (relaxConstraints != null)
- relaxConstraints.setEnabled(currentStatus != null && !currentStatus.isOK());
- }
-
- private void createViewControlsArea(Composite controlsComposite) {
- relaxConstraints = new Button(controlsComposite, SWT.CHECK);
- relaxConstraints.setVisible(false);
- relaxConstraints.setText(ProvUIMessages.ResolutionWizardPage_RelaxedConstraints);
- relaxConstraints.setToolTipText(ProvUIMessages.ResolutionWizardPage_RelaxedConstraintsTip);
- relaxConstraints.setSelection(((ProvisioningOperationWizard) getWizard()).getRelaxedResoltion());
- relaxConstraints.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- ((ProvisioningOperationWizard) getWizard()).setRelaxedResolution(relaxConstraints.getSelection());
- setPageComplete(true);
- }
- });
- }
-
- @Override
- public void setVisible(boolean visible) {
- super.setVisible(visible);
- if (visible)
- relaxConstraints.setSelection(((ProvisioningOperationWizard) getWizard()).getRelaxedResoltion());
}
protected void createSizingInfo(Composite parent) {
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/SelectableIUsPage.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/SelectableIUsPage.java
index 54536c9..a2bddf1 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/SelectableIUsPage.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/SelectableIUsPage.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2008, 2011 IBM Corporation and others.
+ * Copyright (c) 2008, 2013 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
@@ -9,11 +9,11 @@
* IBM Corporation - initial API and implementation
* EclipseSource - ongoing development
* Sonatype, Inc. - ongoing development
+ * Red Hat, Inc. - support for remediation page
*******************************************************************************/
package org.eclipse.equinox.internal.p2.ui.dialogs;
import java.util.ArrayList;
-import org.eclipse.core.runtime.IStatus;
import org.eclipse.equinox.internal.p2.ui.ProvUI;
import org.eclipse.equinox.internal.p2.ui.ProvUIMessages;
import org.eclipse.equinox.internal.p2.ui.model.*;
@@ -28,8 +28,6 @@ import org.eclipse.jface.viewers.*;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
@@ -56,7 +54,6 @@ public class SelectableIUsPage extends ResolutionStatusPage implements IResoluti
protected Display display;
protected Policy policy;
SashForm sashForm;
- Button relaxConstraints;
public SelectableIUsPage(ProvisioningUI ui, ProvisioningOperationWizard wizard, IUElementListRoot root, Object[] initialSelections) {
super("IUSelectionPage", ui, wizard); //$NON-NLS-1$
@@ -163,8 +160,6 @@ public class SelectableIUsPage extends ResolutionStatusPage implements IResoluti
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, false);
controlsComposite.setLayoutData(gd);
- createViewControlsArea(controlsComposite);
-
// The text area shows a description of the selected IU, or error detail if applicable.
iuDetailsGroup = new IUDetailsGroup(sashForm, tableViewer, convertWidthInCharsToPixels(ILayoutConstants.DEFAULT_TABLE_WIDTH), true);
@@ -174,36 +169,6 @@ public class SelectableIUsPage extends ResolutionStatusPage implements IResoluti
Dialog.applyDialogFont(sashForm);
}
- @Override
- public void updateStatus(IUElementListRoot newRoot, ProfileChangeOperation op) {
- super.updateStatus(newRoot, op);
- IStatus currentStatus = getProvisioningWizard().getCurrentStatus();
- if (relaxConstraints != null)
- relaxConstraints.setEnabled(currentStatus != null && !currentStatus.isOK());
- }
-
- private void createViewControlsArea(Composite controlsComposite) {
- relaxConstraints = new Button(controlsComposite, SWT.CHECK);
- relaxConstraints.setVisible(false);
- relaxConstraints.setText(ProvUIMessages.ResolutionWizardPage_RelaxedConstraints);
- relaxConstraints.setToolTipText(ProvUIMessages.ResolutionWizardPage_RelaxedConstraintsTip);
- relaxConstraints.setSelection(((ProvisioningOperationWizard) getWizard()).getRelaxedResoltion());
- relaxConstraints.addSelectionListener(new SelectionAdapter() {
- @Override
- public void widgetSelected(SelectionEvent e) {
- ((ProvisioningOperationWizard) getWizard()).setRelaxedResolution(relaxConstraints.getSelection());
- setPageComplete(true);
- }
- });
- }
-
- @Override
- public void setVisible(boolean visible) {
- super.setVisible(visible);
- if (visible)
- relaxConstraints.setSelection(((ProvisioningOperationWizard) getWizard()).getRelaxedResoltion());
- }
-
private void createSelectButtons(Composite parent) {
Composite buttonParent = new Composite(parent, SWT.NONE);
GridLayout gridLayout = new GridLayout();
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/UninstallWizard.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/UninstallWizard.java
index db6f78b..9743c96 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/UninstallWizard.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/UninstallWizard.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2010 IBM Corporation and others.
+ * Copyright (c) 2007, 2013 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
@@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Sonatype, Inc. - ongoing development
+ * Red Hat, Inc. - support for remediation page
*******************************************************************************/
package org.eclipse.equinox.internal.p2.ui.dialogs;
@@ -88,4 +89,11 @@ public class UninstallWizard extends ProvisioningOperationWizard {
op.setProvisioningContext(getProvisioningContext());
return op;
}
+
+ @Override
+ protected RemediationPage createRemediationPage() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
}
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/UpdateWizard.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/UpdateWizard.java
index 47281e6..835b482 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/UpdateWizard.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/dialogs/UpdateWizard.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2011 IBM Corporation and others.
+ * Copyright (c) 2007, 2013 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
@@ -9,6 +9,7 @@
* IBM Corporation - initial API and implementation
* Genuitec, LLC - added license support
* Sonatype, Inc. - ongoing development
+ * Red Hat, Inc. - support for remediation page
*******************************************************************************/
package org.eclipse.equinox.internal.p2.ui.dialogs;
@@ -16,8 +17,7 @@ import java.util.*;
import org.eclipse.core.runtime.Assert;
import org.eclipse.equinox.internal.p2.ui.ProvUIImages;
import org.eclipse.equinox.internal.p2.ui.ProvUIMessages;
-import org.eclipse.equinox.internal.p2.ui.model.AvailableUpdateElement;
-import org.eclipse.equinox.internal.p2.ui.model.IUElementListRoot;
+import org.eclipse.equinox.internal.p2.ui.model.*;
import org.eclipse.equinox.p2.engine.IProfile;
import org.eclipse.equinox.p2.engine.IProfileRegistry;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
@@ -114,24 +114,32 @@ public class UpdateWizard extends WizardWithLicenses {
}
protected void initializeResolutionModelElements(Object[] selectedElements) {
+ if (selectedElements == null)
+ return;
root = new IUElementListRoot();
- ArrayList<AvailableUpdateElement> list = new ArrayList<AvailableUpdateElement>(selectedElements.length);
- ArrayList<AvailableUpdateElement> selected = new ArrayList<AvailableUpdateElement>(selectedElements.length);
- for (int i = 0; i < selectedElements.length; i++) {
- if (selectedElements[i] instanceof AvailableUpdateElement) {
- AvailableUpdateElement element = (AvailableUpdateElement) selectedElements[i];
- AvailableUpdateElement newElement = new AvailableUpdateElement(root, element.getIU(), element.getIUToBeUpdated(), getProfileId(), shouldShowProvisioningPlanChildren());
- list.add(newElement);
- selected.add(newElement);
- } else if (selectedElements[i] instanceof Update) {
- Update update = (Update) selectedElements[i];
- AvailableUpdateElement newElement = new AvailableUpdateElement(root, update.replacement, update.toUpdate, getProfileId(), shouldShowProvisioningPlanChildren());
- list.add(newElement);
- selected.add(newElement);
+ if (operation instanceof RemediationOperation) {
+ ArrayList<AvailableIUElement> list = remediationPage.transformIUstoIUElements();
+ root.setChildren(list.toArray());
+ planSelections = list.toArray();
+ } else {
+ ArrayList<AvailableUpdateElement> list = new ArrayList<AvailableUpdateElement>(selectedElements.length);
+ ArrayList<AvailableUpdateElement> selected = new ArrayList<AvailableUpdateElement>(selectedElements.length);
+ for (int i = 0; i < selectedElements.length; i++) {
+ if (selectedElements[i] instanceof AvailableUpdateElement) {
+ AvailableUpdateElement element = (AvailableUpdateElement) selectedElements[i];
+ AvailableUpdateElement newElement = new AvailableUpdateElement(root, element.getIU(), element.getIUToBeUpdated(), getProfileId(), shouldShowProvisioningPlanChildren());
+ list.add(newElement);
+ selected.add(newElement);
+ } else if (selectedElements[i] instanceof Update) {
+ Update update = (Update) selectedElements[i];
+ AvailableUpdateElement newElement = new AvailableUpdateElement(root, update.replacement, update.toUpdate, getProfileId(), shouldShowProvisioningPlanChildren());
+ list.add(newElement);
+ selected.add(newElement);
+ }
}
+ root.setChildren(list.toArray());
+ planSelections = selected.toArray();
}
- root.setChildren(list.toArray());
- planSelections = selected.toArray();
}
protected IResolutionErrorReportingPage createErrorReportingPage() {
@@ -186,4 +194,11 @@ public class UpdateWizard extends WizardWithLicenses {
}
return firstPageRoot;
}
+
+ @Override
+ protected RemediationPage createRemediationPage() {
+ remediationPage = new RemediationPage(ui, this, root, operation);
+ return remediationPage;
+ }
+
}
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/messages.properties b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/messages.properties
index fc021bf..79843cc 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/messages.properties
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/messages.properties
@@ -214,6 +214,22 @@ AvailableIUsPage_ShowLatestVersions=Show only the &latest versions of available
AvailableIUsPage_SingleSelectionCount={0} item selected
AvailableIUsPage_Title=Available Software
AvailableIUWrapper_AllAreInstalled=All items are installed
+InstallRemediationPage_Title=Install Remediation Page
+InstallRemediationPage_Description=The installation cannot be completed as requested.
+UpdateRemediationPage_Title=Update Remediation Page
+UpdateRemediationPage_Description=The update cannot be completed as requested.
+RemediationPage_SubDescription=Chose one of the following alternate solutions:
+RemediationPage_NoSolutionFound=No solution found.
+RemediationPage_BeingInstalledSection=How do you want to change the software being installed?
+RemediationPage_InstalledSection=How do you want to alter the current installation?
+RemediationPage_BeingInstalledSection_AllowPartialInstall=install less item than originally requested
+RemediationPage_BeingInstalledSection_AllowDifferentVersion=install different version than originally requested
+RemediationPage_InstalledSection_AllowInstalledUpdate=update items already installed
+RemediationPage_InstalledSection_AllowInstalledRemoval=remove items already installed
+RemediationPage_BestSolutionBeingInstalledRelaxed=Keep my installation the same and modify the items being installed to be compatible
+RemediationPage_BestSolutionInstallationRelaxed=Update my installation to handle the items being installed
+RemediationPage_BestSolutionBuilt=Build my own solution
+
IUViewQueryContext_AllAreInstalledDescription=You can uncheck the 'Hide items that are already installed' check box to see all items.
Label_Profiles=All Software Profiles
Label_Repositories=Known Repositories
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/model/AvailableIUElement.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/model/AvailableIUElement.java
index 4cb5b9d..21499f3 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/model/AvailableIUElement.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/model/AvailableIUElement.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2011 IBM Corporation and others.
+ * Copyright (c) 2007, 2013 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
@@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Sonatype, Inc. - ongoing development
+ * Red Hat, Inc. - support for remediation page
*******************************************************************************/
package org.eclipse.equinox.internal.p2.ui.model;
@@ -38,6 +39,7 @@ public class AvailableIUElement extends QueriedElement implements IIUElement {
boolean isInstalled = false;
boolean isUpdate = false;
boolean isPatch = false;
+ boolean isUninstall = false;
// Currently this variable is not settable due to the
// poor performance of sizing, but it is kept here for future improvement.
@@ -68,6 +70,8 @@ public class AvailableIUElement extends QueriedElement implements IIUElement {
return isInstalled ? ProvUIImages.IMG_DISABLED_PATCH_IU : ProvUIImages.IMG_PATCH_IU;
else if (isInstalled)
return ProvUIImages.IMG_DISABLED_IU;
+ else if (isUninstall)
+ return ProvUIImages.IMG_REMOVED_IU;
return ProvUIImages.IMG_IU;
}
@@ -199,6 +203,14 @@ public class AvailableIUElement extends QueriedElement implements IIUElement {
return isUpdate;
}
+ public void setIsUninstall(boolean isUninstall) {
+ this.isUninstall = isUninstall;
+ }
+
+ public boolean isUninstall() {
+ return isUninstall;
+ }
+
public void setIsPatch(boolean isPatch) {
this.isPatch = isPatch;
}
diff --git a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/p2/ui/ProvisioningUI.java b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/p2/ui/ProvisioningUI.java
index bccd352..6b05df2 100644
--- a/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/p2/ui/ProvisioningUI.java
+++ b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/p2/ui/ProvisioningUI.java
@@ -133,16 +133,6 @@ public class ProvisioningUI {
}
/**
- * @since 2.2
- */
- public RelaxedUpdateInstallOperation getRelaxedUpdateOperation(ProvisioningContext context) {
- RelaxedUpdateInstallOperation luckyOperation = new RelaxedUpdateInstallOperation(getSession());
- luckyOperation.setProfileId(getProfileId());
- luckyOperation.setProvisioningContext(context);
- return luckyOperation;
- }
-
- /**
* Return an install operation that describes installing the specified IInstallableUnits from the
* provided list of repositories.
*
@@ -237,6 +227,23 @@ public class ProvisioningUI {
* @return the wizard return code
*/
public int openUpdateWizard(boolean skipSelectionsPage, UpdateOperation operation, LoadMetadataRepositoryJob job) {
+ return openUpdateWizard(skipSelectionsPage, operation, null, job);
+
+ }
+
+ /**
+ * Open an update wizard for the specified update operation and remediationOperation.
+ *
+ * @param skipSelectionsPage <code>true</code> if the selection page should be skipped so that the user is
+ * viewing the resolution results. <code>false</code> if the update selection page should be shown first.
+ * @param operation the operation describing the proposed update. Must not be <code>null</code>.
+ * @param remediationOperation the alternate operations if the proposed update failed. May be <code>null</code>.
+ * @param job a repository load job that is loading or has already loaded the repositories. Can be used to pass along
+ * an in-memory repository reference to the wizard.
+ *
+ * @return the wizard return code
+ */
+ public int openUpdateWizard(boolean skipSelectionsPage, UpdateOperation operation, RemediationOperation remediationOperation, LoadMetadataRepositoryJob job) {
if (getPolicy().getUpdateWizardStyle() == Policy.UPDATE_STYLE_SINGLE_IUS && UpdateSingleIUWizard.validFor(operation)) {
UpdateSingleIUWizard wizard = new UpdateSingleIUWizard(this, operation);
WizardDialog dialog = new WizardDialog(ProvUI.getDefaultParentShell(), wizard);
@@ -245,6 +252,7 @@ public class ProvisioningUI {
return dialog.open();
}
UpdateWizard wizard = new UpdateWizard(this, operation, operation.getSelectedUpdates(), job);
+ wizard.setRemediationOperation(remediationOperation);
wizard.setSkipSelectionsPage(skipSelectionsPage);
WizardDialog dialog = new ProvisioningWizardDialog(ProvUI.getDefaultParentShell(), wizard);
dialog.create();