diff options
author | irbull | 2011-10-17 22:46:26 +0000 |
---|---|---|
committer | irbull | 2011-10-17 22:46:26 +0000 |
commit | 60787e0502dcc0bb28da95ca2d989fe7892e765f (patch) | |
tree | 9a52090ae2a5502ee55031f40ac125cf6553cbe2 | |
parent | e33a37cf824abdbbe2044b738f664d2527e7a79c (diff) | |
download | rt.equinox.p2-60787e0502dcc0bb28da95ca2d989fe7892e765f.tar.gz rt.equinox.p2-60787e0502dcc0bb28da95ca2d989fe7892e765f.tar.xz rt.equinox.p2-60787e0502dcc0bb28da95ca2d989fe7892e765f.zip |
Bug 261928 : Adds a Relaxed Constraint Optionv20111017-2246
This will relax the constraints when an update / install fails. This
allows a user to try again with a slighly different provisioning plan.
This is just the start of this work, but it should give us a chance to
test it out and make changes in future builds.
10 files changed, 225 insertions, 1 deletions
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 5d72f5d83..0c930e7aa 100644 --- a/bundles/org.eclipse.equinox.p2.operations/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.equinox.p2.operations/META-INF/MANIFEST.MF @@ -16,6 +16,7 @@ Bundle-RequiredExecutionEnvironment: J2SE-1.5, Bundle-ActivationPolicy: lazy Import-Package: org.eclipse.equinox.internal.p2.core.helpers, org.eclipse.equinox.internal.p2.director, + org.eclipse.equinox.internal.p2.metadata.query, org.eclipse.equinox.internal.p2.repository.helpers, org.eclipse.equinox.internal.provisional.configurator, org.eclipse.equinox.internal.provisional.p2.core.eventbus, 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 b170e415c..918011323 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,6 +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 OperationFactory_noAgent; public static String OperationFactory_noIUFound; 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 48fa2ae64..2d2253ea5 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 @@ -42,6 +42,9 @@ 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 + OperationFactory_noAgent=This installation has not been configured properly. No provisioning agent can be found. OperationFactory_noIUFound=No IU could be found for {0}.
\ No newline at end of file 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 new file mode 100644 index 000000000..a0e20dd60 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.operations/src/org/eclipse/equinox/p2/operations/RelaxedUpdateInstallOperation.java @@ -0,0 +1,111 @@ +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 + */ +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)); + } + } + } + //return planner.getProvisioningPlan(finalChangeRequest, context, null); + } + + @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.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 bd31e0af3..23247938f 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 @@ -158,6 +158,7 @@ public class ProvUIMessages extends NLS { public static String ResolutionWizardPage_ErrorStatus; public static String ResolutionWizardPage_NoSelections; public static String ResolutionWizardPage_WarningInfoStatus; + public static String ResolutionWizardPage_RelaxedConstraints; public static String ResolutionStatusPage_ErrorIULocked; // Dialogs 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 e1d12f642..78e62e440 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 @@ -49,6 +49,7 @@ public abstract class ProvisioningOperationWizard extends Wizard { private ProvisioningContext provisioningContext; protected LoadMetadataRepositoryJob repoPreloadJob; IStatus couldNotResolveStatus = Status.OK_STATUS; // we haven't tried and failed + boolean resolveWithRelaxedConstraints = false; boolean waitingForOtherJobs = false; @@ -191,6 +192,34 @@ 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.getLuckyOperation(provisioningContext); + operation.setProvisioningContext(provisioningContext); + try { + runnableContext.run(true, true, new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) { + operation.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); + } + } + planChanged(); + } + /** * Recompute the provisioning plan based on the items in the IUElementListRoot and the given provisioning context. * Report progress using the specified runnable context. This method may be called before the page is created. @@ -198,6 +227,10 @@ public abstract class ProvisioningOperationWizard extends Wizard { * @param runnableContext */ public void recomputePlan(IRunnableContext runnableContext) { + if (resolveWithRelaxedConstraints) { + recomputePlanWithRelaxedConstraints(runnableContext); + return; + } couldNotResolveStatus = Status.OK_STATUS; provisioningContext = getProvisioningContext(); initializeResolutionModelElements(getOperationSelections()); @@ -350,4 +383,8 @@ public abstract class ProvisioningOperationWizard extends Wizard { public boolean statusOverridesOperation() { return false; } + + public void setRelaxedResolution(boolean value) { + this.resolveWithRelaxedConstraints = value; + } } 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 556f2999f..a0033f10d 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 @@ -15,6 +15,7 @@ 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; @@ -24,10 +25,13 @@ import org.eclipse.equinox.p2.operations.ProvisioningJob; import org.eclipse.equinox.p2.query.IQueryable; import org.eclipse.equinox.p2.ui.ProvisioningUI; import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; 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; @@ -51,6 +55,7 @@ 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$ @@ -117,6 +122,20 @@ public abstract class ResolutionResultsWizardPage extends ResolutionStatusPage { sashForm.setWeights(getSashWeights()); Dialog.applyDialogFont(sashForm); + // Controls for filtering/presentation/site selection + Composite controlsComposite = new Composite(composite, SWT.NONE); + gridLayout = new GridLayout(); + gridLayout.marginWidth = 0; + gridLayout.marginHeight = 0; + gridLayout.numColumns = 2; + gridLayout.makeColumnsEqualWidth = true; + gridLayout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); + controlsComposite.setLayout(layout); + 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() { @@ -124,7 +143,6 @@ public abstract class ResolutionResultsWizardPage extends ResolutionStatusPage { setDetailText(resolvedOperation); } }); - updateStatus(input, resolvedOperation); setDrilldownElements(input, resolvedOperation); treeViewer.setInput(input); } @@ -146,6 +164,18 @@ public abstract class ResolutionResultsWizardPage extends ResolutionStatusPage { } } + private void createViewControlsArea(Composite controlsComposite) { + relaxConstraints = new Button(controlsComposite, SWT.CHECK); + relaxConstraints.setText(ProvUIMessages.ResolutionWizardPage_RelaxedConstraints); + relaxConstraints.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + ((ProvisioningOperationWizard) getWizard()).setRelaxedResolution(relaxConstraints.getSelection()); + setPageComplete(true); + } + }); + } + protected void createSizingInfo(Composite parent) { // Default is to do nothing } 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 16dfec241..d6a85db91 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 @@ -27,6 +27,8 @@ 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.*; @@ -53,6 +55,7 @@ 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$ @@ -147,6 +150,20 @@ public class SelectableIUsPage extends ResolutionStatusPage implements IResoluti // Select and Deselect All buttons createSelectButtons(composite); + // Controls for filtering/presentation/site selection + Composite controlsComposite = new Composite(composite, SWT.NONE); + gridLayout = new GridLayout(); + gridLayout.marginWidth = 0; + gridLayout.marginHeight = 0; + gridLayout.numColumns = 2; + gridLayout.makeColumnsEqualWidth = true; + gridLayout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); + controlsComposite.setLayout(layout); + 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); @@ -156,6 +173,18 @@ public class SelectableIUsPage extends ResolutionStatusPage implements IResoluti Dialog.applyDialogFont(sashForm); } + private void createViewControlsArea(Composite controlsComposite) { + relaxConstraints = new Button(controlsComposite, SWT.CHECK); + relaxConstraints.setText(ProvUIMessages.ResolutionWizardPage_RelaxedConstraints); + relaxConstraints.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + ((ProvisioningOperationWizard) getWizard()).setRelaxedResolution(relaxConstraints.getSelection()); + setPageComplete(true); + } + }); + } + 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/messages.properties b/bundles/org.eclipse.equinox.p2.ui/src/org/eclipse/equinox/internal/p2/ui/messages.properties index 03126b761..e1db8c28f 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 @@ -106,8 +106,10 @@ ResolutionWizardPage_Canceled=The operation was cancelled. ResolutionWizardPage_ErrorStatus=The operation cannot be completed. See the details. ResolutionWizardPage_NoSelections=There were no installable units selected when the plan was computed. ResolutionWizardPage_WarningInfoStatus=Your original request has been modified. See the details. +ResolutionWizardPage_RelaxedConstraints=Run with relaxed constraints. ResolutionStatusPage_ErrorIULocked=Insufficient access privileges to apply this update.\n\n{0} + AcceptLicensesWizardPage_AcceptMultiple=I &accept the terms of the license agreements AcceptLicensesWizardPage_AcceptSingle=I &accept the terms of the license agreement AcceptLicensesWizardPage_ItemsLabel=&Licenses: 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 6b8625647..6fce2d75b 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 @@ -132,6 +132,13 @@ public class ProvisioningUI { return profileId; } + public RelaxedUpdateInstallOperation getLuckyOperation(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. |