blob: 592489712a984333deab60fbf3788bfb57537366 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2015 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
* 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<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();
}
}
/*
* 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(new Runnable() {
@Override
public void run() {
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(), new Runnable() {
@Override
public void run() {
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 installHandlerStatus != null && !installHandlerStatus.isOK() && couldNotResolveStatus == installHandlerStatus;
}
}