| /******************************************************************************* |
| * Copyright (c) 2007, 2018 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Sonatype, Inc. - ongoing development |
| * Red Hat, Inc. - support for remediation page |
| * Lars Vogel <Lars.Vogel@vogella.com> - Bug 479145 |
| *******************************************************************************/ |
| package org.eclipse.equinox.internal.p2.ui.dialogs; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import org.eclipse.core.runtime.IStatus; |
| 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.*; |
| import org.eclipse.equinox.p2.ui.LoadMetadataRepositoryJob; |
| import org.eclipse.equinox.p2.ui.ProvisioningUI; |
| import org.eclipse.jface.dialogs.IDialogConstants; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.wizard.IWizardPage; |
| import org.eclipse.jface.wizard.WizardPage; |
| import org.eclipse.swt.custom.BusyIndicator; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.ui.PlatformUI; |
| |
| /** |
| * An install wizard that allows the users to browse all of the repositories and |
| * search/select for items to install. |
| * |
| * @since 3.6 |
| */ |
| public class InstallWizard extends WizardWithLicenses { |
| |
| SelectableIUsPage errorReportingPage; |
| boolean ignoreSelectionChanges = false; |
| IStatus installHandlerStatus; |
| |
| public InstallWizard(ProvisioningUI ui, InstallOperation operation, Collection<IInstallableUnit> initialSelections, |
| LoadMetadataRepositoryJob preloadJob) { |
| super(ui, operation, initialSelections == null ? null : initialSelections.toArray(), preloadJob); |
| setWindowTitle(ProvUIMessages.InstallIUOperationLabel); |
| setDefaultPageImageDescriptor(ProvUIImages.getImageDescriptor(ProvUIImages.WIZARD_BANNER_INSTALL)); |
| } |
| |
| @Override |
| protected ResolutionResultsWizardPage createResolutionPage() { |
| return new InstallWizardPage(ui, this, root, operation); |
| } |
| |
| @Override |
| protected ISelectableIUsPage createMainPage(IUElementListRoot input, Object[] selections) { |
| mainPage = new AvailableIUsPage(ui, this); |
| if (selections != null && selections.length > 0) |
| mainPage.setCheckedElements(selections); |
| return mainPage; |
| |
| } |
| |
| @Override |
| protected void initializeResolutionModelElements(Object[] selectedElements) { |
| if (selectedElements == null) |
| return; |
| root = new IUElementListRoot(ui); |
| if (operation instanceof RemediationOperation) { |
| AvailableIUElement[] elements = ElementUtils |
| .requestToElement(((RemediationOperation) operation).getCurrentRemedy(), true); |
| root.setChildren(elements); |
| planSelections = elements; |
| } else { |
| ArrayList<AvailableIUElement> list = new ArrayList<>(selectedElements.length); |
| ArrayList<AvailableIUElement> selections = new ArrayList<>(selectedElements.length); |
| for (Object selectedElement : selectedElements) { |
| IInstallableUnit iu = ElementUtils.getIU(selectedElement); |
| if (iu != null) { |
| AvailableIUElement element = new AvailableIUElement(root, iu, getProfileId(), |
| shouldShowProvisioningPlanChildren()); |
| list.add(element); |
| selections.add(element); |
| } |
| } |
| root.setChildren(list.toArray()); |
| planSelections = selections.toArray(); |
| } |
| } |
| |
| /* |
| * Overridden to dynamically determine which page to get selections from. |
| */ |
| @Override |
| protected Object[] getOperationSelections() { |
| return getOperationSelectionsPage().getCheckedIUElements(); |
| } |
| |
| /* |
| * Get the page that is driving operation selections. This is usually the main |
| * page, but it could be error page if there was a resolution error and the user |
| * decides to change selections and try again without going back. |
| */ |
| protected ISelectableIUsPage getOperationSelectionsPage() { |
| IWizardPage page = getContainer().getCurrentPage(); |
| if (page instanceof ISelectableIUsPage) |
| return (ISelectableIUsPage) page; |
| // return the main page if we weren't on main or error page |
| return mainPage; |
| } |
| |
| @Override |
| protected ProvisioningContext getProvisioningContext() { |
| return ((AvailableIUsPage) mainPage).getProvisioningContext(); |
| } |
| |
| @Override |
| protected IResolutionErrorReportingPage createErrorReportingPage() { |
| if (root == null) |
| errorReportingPage = new SelectableIUsPage(ui, this, null, null); |
| else |
| errorReportingPage = new SelectableIUsPage(ui, this, root, root.getChildren(root)); |
| errorReportingPage.setTitle(ProvUIMessages.InstallWizardPage_Title); |
| errorReportingPage.setDescription(ProvUIMessages.PreselectedIUInstallWizard_Description); |
| errorReportingPage.updateStatus(root, operation); |
| return errorReportingPage; |
| } |
| |
| @Override |
| protected RemediationPage createRemediationPage() { |
| remediationPage = new RemediationPage(ui, this, root, operation); |
| return remediationPage; |
| } |
| |
| @Override |
| protected ProfileChangeOperation getProfileChangeOperation(Object[] elements) { |
| InstallOperation op = new InstallOperation(ui.getSession(), ElementUtils.elementsToIUs(elements)); |
| op.setProfileId(getProfileId()); |
| // op.setRootMarkerKey(getRootMarkerKey()); |
| return op; |
| } |
| |
| @Override |
| protected boolean shouldUpdateErrorPageModelOnPlanChange() { |
| // We don't want the root of the error page to change unless we are on the |
| // main page. For example, if we are on the error page, change checkmarks, and |
| // resolve again with an error, we wouldn't want the root items to change in the |
| // error page. |
| return getContainer().getCurrentPage() == mainPage && super.shouldUpdateErrorPageModelOnPlanChange(); |
| } |
| |
| @Override |
| protected void planChanged() { |
| super.planChanged(); |
| synchSelections(getOperationSelectionsPage()); |
| } |
| |
| /* |
| * overridden to ensure that the main page selections stay in synch with changes |
| * to the error page. |
| */ |
| @Override |
| public void operationSelectionsChanged(ISelectableIUsPage page) { |
| if (ignoreSelectionChanges) |
| return; |
| super.operationSelectionsChanged(page); |
| // If we are on the error page, resolution has failed. |
| // Our ability to move on depends on whether the selections have changed. |
| // If they are the same selections, then we are not complete until selections |
| // are changed. |
| if (getOperationSelectionsPage() == errorPage) |
| ((WizardPage) errorPage).setPageComplete( |
| pageSelectionsHaveChanged(errorPage) && errorPage.getCheckedIUElements().length > 0); |
| synchSelections(page); |
| } |
| |
| private void synchSelections(ISelectableIUsPage triggeringPage) { |
| // We don't want our programmatic changes to cause all this to happen again |
| ignoreSelectionChanges = true; |
| try { |
| if (triggeringPage == errorReportingPage) { |
| mainPage.setCheckedElements(triggeringPage.getCheckedIUElements()); |
| } else if (triggeringPage == mainPage) { |
| errorReportingPage.setCheckedElements(triggeringPage.getCheckedIUElements()); |
| } |
| } finally { |
| ignoreSelectionChanges = false; |
| } |
| } |
| |
| /* |
| * Overridden to check whether there are UpdateManager install handlers in the |
| * item to be installed. Operations don't know about this compatibility issue. |
| */ |
| @Override |
| public IStatus getCurrentStatus() { |
| IStatus originalStatus = super.getCurrentStatus(); |
| int sev = originalStatus.getSeverity(); |
| // Use the previously computed status if the user cancelled or if we were |
| // already in error. |
| // If we don't have an operation or a plan, we can't check this condition |
| // either, so just |
| // use the normal status. |
| if (sev == IStatus.CANCEL || sev == IStatus.ERROR || operation == null |
| || operation.getProvisioningPlan() == null) { |
| return originalStatus; |
| } |
| // Does the plan require install handler support? |
| installHandlerStatus = UpdateManagerCompatibility.getInstallHandlerStatus(operation.getProvisioningPlan()); |
| if (!installHandlerStatus.isOK()) { |
| // Set the status into the wizard. This ensures future calls to this method |
| // won't |
| // repeat the work (and prompting). |
| couldNotResolveStatus = installHandlerStatus; |
| |
| // Is the update manager installer present? If so, offer to open it. |
| // In either case, the failure will be reported in this wizard. |
| if (ProvUI.isUpdateManagerInstallerPresent()) { |
| PlatformUI.getWorkbench().getDisplay().asyncExec(() -> { |
| Shell shell = ProvUI.getDefaultParentShell(); |
| MessageDialog dialog = new MessageDialog(shell, ProvUIMessages.Policy_RequiresUpdateManagerTitle, |
| null, ProvUIMessages.Policy_RequiresUpdateManagerMessage, MessageDialog.WARNING, |
| new String[] { ProvUIMessages.LaunchUpdateManagerButton, IDialogConstants.CANCEL_LABEL }, |
| 0); |
| if (dialog.open() == 0) |
| BusyIndicator.showWhile(shell.getDisplay(), UpdateManagerCompatibility::openInstaller); |
| }); |
| } |
| return installHandlerStatus; |
| } |
| return originalStatus; |
| } |
| |
| /* |
| * When we've found an install handler, that status trumps anything that the |
| * operation might have determined. We are relying here on the knowledge that |
| * the wizard's couldNotResolveStatus is reset on every new resolution, so that |
| * status only holds the installHandler status when it is the current status. |
| * The installHandlerStatus must be non-OK for it to matter at all. |
| * |
| */ |
| @Override |
| public boolean statusOverridesOperation() { |
| return super.statusOverridesOperation() || (installHandlerStatus != null && !installHandlerStatus.isOK() |
| && couldNotResolveStatus == installHandlerStatus); |
| } |
| } |