blob: 02d246f2983a49517e7111f0ce6d86794d147f93 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2007 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
*******************************************************************************/
package org.eclipse.update.internal.ui.wizards;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Display;
import org.eclipse.update.configuration.IInstallConfiguration;
import org.eclipse.update.core.IFeature;
import org.eclipse.update.core.IFeatureReference;
import org.eclipse.update.core.IIncludedFeatureReference;
import org.eclipse.update.core.ISite;
import org.eclipse.update.core.ISiteFeatureReference;
import org.eclipse.update.core.IVerificationListener;
import org.eclipse.update.core.SiteManager;
import org.eclipse.update.core.model.InstallAbortedException;
import org.eclipse.update.internal.core.FeatureDownloadException;
import org.eclipse.update.internal.core.LiteFeature;
import org.eclipse.update.internal.core.UpdateCore;
import org.eclipse.update.internal.operations.DuplicateConflictsValidator;
import org.eclipse.update.internal.operations.InstallOperation;
import org.eclipse.update.internal.operations.UpdateUtils;
import org.eclipse.update.internal.ui.UpdateUI;
import org.eclipse.update.internal.ui.UpdateUIImages;
import org.eclipse.update.internal.ui.UpdateUIMessages;
import org.eclipse.update.internal.ui.security.JarVerificationService;
import org.eclipse.update.operations.IBatchOperation;
import org.eclipse.update.operations.IFeatureOperation;
import org.eclipse.update.operations.IInstallFeatureOperation;
import org.eclipse.update.operations.IOperation;
import org.eclipse.update.operations.IOperationListener;
import org.eclipse.update.operations.OperationsManager;
import org.eclipse.update.search.UpdateSearchRequest;
public class InstallWizard2
extends Wizard
implements IOperationListener, ISearchProvider {
private ReviewPage reviewPage;
private LicensePage licensePage;
private OptionalFeaturesPage optionalFeaturesPage;
private TargetPage targetPage;
private IInstallConfiguration config;
private int installCount = 0;
private UpdateSearchRequest searchRequest;
private ArrayList jobs;
private boolean needsRestart;
private static boolean isRunning;
private IBatchOperation installOperation;
private Job job;
public static final Object jobFamily = new Object();
private IJobChangeListener jobListener;
private boolean isUpdate;
public InstallWizard2(UpdateSearchRequest searchRequest, IInstallFeatureOperation[] jobs, boolean isUpdate) {
this (searchRequest, new ArrayList(Arrays.asList(jobs)), isUpdate);
}
public InstallWizard2(UpdateSearchRequest searchRequest, ArrayList jobs, boolean isUpdate) {
this.isUpdate = isUpdate;
this.searchRequest = searchRequest;
this.jobs = jobs;
isRunning = true;
setDialogSettings(UpdateUI.getDefault().getDialogSettings());
setDefaultPageImageDescriptor(UpdateUIImages.DESC_UPDATE_WIZ);
setForcePreviousAndNextButtons(true);
setNeedsProgressMonitor(true);
setWindowTitle(UpdateUIMessages.InstallWizard_wtitle);
}
public int getInstallCount() {
return installCount;
}
public boolean isRestartNeeded() {
return installCount > 0 && needsRestart; // or == selectedJobs.length
}
public boolean performCancel() {
isRunning = false;
if (targetPage != null)
targetPage.removeAddedSites();
return super.performCancel();
}
/**
* @see Wizard#performFinish()
*/
public boolean performFinish() {
IInstallFeatureOperation[] selectedJobs = reviewPage.getSelectedJobs();
// Check for duplication conflicts
ArrayList conflicts = DuplicateConflictsValidator.computeDuplicateConflicts(selectedJobs, config);
if (conflicts != null) {
DuplicateConflictsDialog dialog = new DuplicateConflictsDialog(getShell(), conflicts);
if (dialog.open() != 0)
return false;
}
if (Job.getJobManager().find(jobFamily).length > 0) {
// another update/install job is running, need to wait to finish or cancel old job
boolean proceed = MessageDialog.openQuestion(
UpdateUI.getActiveWorkbenchShell(),
UpdateUIMessages.InstallWizard_anotherJobTitle,
UpdateUIMessages.InstallWizard_anotherJob);
if (!proceed)
return false; // cancel this job, and let the old one go on
}
// set the install operation
installOperation = getBatchInstallOperation(selectedJobs);
if (installOperation != null)
launchInBackground();
return true;
}
public void addPages() {
reviewPage = new ReviewPage(isUpdate, searchRequest, jobs);
addPage(reviewPage);
try {
// config = UpdateUtils.createInstallConfiguration();
config = SiteManager.getLocalSite().getCurrentConfiguration();
} catch (CoreException e) {
UpdateUI.logException(e);
}
licensePage = new LicensePage(true);
addPage(licensePage);
optionalFeaturesPage = new OptionalFeaturesPage(config);
addPage(optionalFeaturesPage);
targetPage = new TargetPage(config, isUpdate);
addPage(targetPage);
}
private boolean isPageRequired(IWizardPage page) {
if (page == null)
return false;
if (page.equals(licensePage)) {
return OperationsManager.hasSelectedJobsWithLicenses(
reviewPage.getSelectedJobs());
}
if (page.equals(optionalFeaturesPage)) {
return OperationsManager.hasSelectedJobsWithOptionalFeatures(
reviewPage.getSelectedJobs());
}
if (page.equals(targetPage)) {
return reviewPage.getSelectedJobs().length > 0;
}
return true;
}
public IWizardPage getNextPage(IWizardPage page) {
IWizardPage[] pages = getPages();
boolean start = false;
IWizardPage nextPage = null;
if (page.equals(reviewPage)) {
updateDynamicPages();
}
for (int i = 0; i < pages.length; i++) {
if (pages[i].equals(page)) {
start = true;
} else if (start) {
if (isPageRequired(pages[i])) {
nextPage = pages[i];
break;
}
}
}
return nextPage;
}
private void updateDynamicPages() {
if (licensePage != null) {
IInstallFeatureOperation[] licenseJobs =
OperationsManager.getSelectedJobsWithLicenses(
reviewPage.getSelectedJobs());
licensePage.setJobs(licenseJobs);
}
if (optionalFeaturesPage != null) {
IInstallFeatureOperation[] optionalJobs =
OperationsManager.getSelectedJobsWithOptionalFeatures(
reviewPage.getSelectedJobs());
optionalFeaturesPage.setJobs(optionalJobs);
}
if (targetPage != null) {
IInstallFeatureOperation[] installJobs =
reviewPage.getSelectedJobs();
targetPage.setJobs(installJobs);
}
}
public boolean canFinish() {
IWizardPage page = getContainer().getCurrentPage();
return page.equals(targetPage) && page.isPageComplete();
}
private void preserveOriginatingURLs(
IFeature feature,
IFeatureReference[] optionalFeatures) {
// walk the hierarchy and preserve the originating URL
// for all the optional features that are not chosen to
// be installed.
URL url = feature.getSite().getURL();
try {
IIncludedFeatureReference[] irefs =
feature.getIncludedFeatureReferences();
for (int i = 0; i < irefs.length; i++) {
IIncludedFeatureReference iref = irefs[i];
boolean preserve = false;
if (iref.isOptional()) {
boolean onTheList = false;
for (int j = 0; j < optionalFeatures.length; j++) {
if (optionalFeatures[j].equals(iref)) {
//was on the list
onTheList = true;
break;
}
}
if (!onTheList)
preserve = true;
}
if (preserve) {
try {
String id =
iref.getVersionedIdentifier().getIdentifier();
UpdateUI.setOriginatingURL(id, url);
} catch (CoreException e) {
// Silently ignore
}
} else {
try {
IFeature ifeature = iref.getFeature(null);
preserveOriginatingURLs(ifeature, optionalFeatures);
} catch (CoreException e) {
// Silently ignore
}
}
}
} catch (CoreException e) {
// Silently ignore
}
}
/* (non-Javadoc)
* @see org.eclipse.update.operations.IOperationListener#afterExecute(org.eclipse.update.operations.IOperation)
*/
public boolean afterExecute(IOperation operation, Object data) {
if (!(operation instanceof IInstallFeatureOperation))
return true;
IInstallFeatureOperation job = (IInstallFeatureOperation) operation;
IFeature oldFeature = job.getOldFeature();
if (oldFeature == null && job.getOptionalFeatures() != null)
preserveOriginatingURLs(
job.getFeature(),
job.getOptionalFeatures());
installCount++;
return true;
}
/* (non-Javadoc)
* @see org.eclipse.update.operations.IOperationListener#beforeExecute(org.eclipse.update.operations.IOperation)
*/
public boolean beforeExecute(IOperation operation, Object data) {
return true;
}
/* (non-Javadoc)
* @see org.eclipse.update.internal.ui.wizards.ISearchProvider2#getSearchRequest()
*/
public UpdateSearchRequest getSearchRequest() {
return searchRequest;
}
public static synchronized boolean isRunning() {
return isRunning || Job.getJobManager().find(jobFamily).length > 0;
}
private IBatchOperation getBatchInstallOperation(final IInstallFeatureOperation[] selectedJobs) {
final IVerificationListener verificationListener =new JarVerificationService(
//InstallWizard.this.getShell());
UpdateUI.getActiveWorkbenchShell());
// setup jobs with the correct environment
IInstallFeatureOperation[] operations = new IInstallFeatureOperation[selectedJobs.length];
for (int i = 0; i < selectedJobs.length; i++) {
IInstallFeatureOperation job = selectedJobs[i];
IFeature[] unconfiguredOptionalFeatures = null;
IFeatureReference[] optionalFeatures = null;
if (UpdateUtils.hasOptionalFeatures(job.getFeature())) {
optionalFeatures = optionalFeaturesPage.getCheckedOptionalFeatures(job);
unconfiguredOptionalFeatures = optionalFeaturesPage.getUnconfiguredOptionalFeatures(job, job.getTargetSite());
}
IInstallFeatureOperation op =
OperationsManager
.getOperationFactory()
.createInstallOperation(
job.getTargetSite(),
job.getFeature(),
optionalFeatures,
unconfiguredOptionalFeatures,
verificationListener);
operations[i] = op;
}
return OperationsManager.getOperationFactory().createBatchInstallOperation(operations);
}
private void launchInBackground() {
// Downloads the feature content in the background.
// The job listener will then install the feature when download is finished.
// TODO: should we cancel existing jobs?
if (jobListener != null)
Job.getJobManager().removeJobChangeListener(jobListener);
if (job != null)
Job.getJobManager().cancel(job);
jobListener = new UpdateJobChangeListener();
Job.getJobManager().addJobChangeListener(jobListener);
job = new Job(UpdateUIMessages.InstallWizard_jobName) {
public IStatus run(IProgressMonitor monitor) {
if (download(monitor))
return Status.OK_STATUS;
else {
isRunning = false;
return Status.CANCEL_STATUS;
}
}
public boolean belongsTo(Object family) {
return InstallWizard2.jobFamily == family;
}
};
job.setUser(true);
job.setPriority(Job.INTERACTIVE);
// if (wait) {
// progressService.showInDialog(workbench.getActiveWorkbenchWindow().getShell(), job);
// }
job.schedule();
}
private boolean install(IProgressMonitor monitor) {
// Installs the (already downloaded) features and prompts for restart
try {
needsRestart = installOperation.execute(monitor, InstallWizard2.this);
UpdateUI.getStandardDisplay().asyncExec(new Runnable() {
public void run() {
UpdateUI.requestRestart(InstallWizard2.this.isRestartNeeded());
}
});
} catch (final InvocationTargetException e) {
final Throwable targetException = e.getTargetException();
if (!(targetException instanceof InstallAbortedException)){
UpdateUI.getStandardDisplay().syncExec(new Runnable() {
public void run() {
UpdateUI.logException(targetException);
}
});
}
return false;
} catch (CoreException e) {
return false;
} finally {
isRunning = false;
}
return true;
}
private boolean download(final IProgressMonitor monitor) {
// Downloads the feature content.
// This method is called from a background job.
// If download fails, the user is prompted to retry.
try {
IFeatureOperation[] ops = installOperation.getOperations();
monitor.beginTask(UpdateUIMessages.InstallWizard_download, 5 * ops.length);
for (int i = 0; i < ops.length; i++) {
IInstallFeatureOperation op = (IInstallFeatureOperation)ops[i];
try {
String featureName = op.getFeature().getLabel();
if ((featureName == null ) || (featureName.trim() == "") ) { //$NON-NLS-1$
featureName = op.getFeature().getVersionedIdentifier().getIdentifier();
}
SubProgressMonitor featureDownloadMonitor = new SubProgressMonitor(monitor, 2);
featureDownloadMonitor.beginTask(featureName, 2);
featureDownloadMonitor.subTask(NLS.bind(UpdateUIMessages.InstallWizard_downloadingFeatureJar, featureName));
if (op.getFeature() instanceof LiteFeature) {
ISiteFeatureReference featureReference = getFeatureReference(op.getFeature());
IFeature feature = featureReference.getFeature(featureDownloadMonitor);
if (op instanceof InstallOperation) {
((InstallOperation)op).setFeature(feature);
}
}
//featureDownloadMonitor.worked(1);
SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, 3);
UpdateUtils.downloadFeatureContent(op.getTargetSite(), op.getFeature(), op.getOptionalFeatures(), subMonitor);
} catch (final CoreException e) {
if(e instanceof FeatureDownloadException){
boolean retry = retryDownload((FeatureDownloadException)e);
if (retry) {
// redownload current feature
i--;
continue;
}
} else {
UpdateCore.log(e);
if ( !monitor.isCanceled()) {
Display.getDefault().syncExec( new Runnable () {
public void run() {
IStatus status = new Status( IStatus.ERROR, UpdateUI.getPluginId(), IStatus.OK, UpdateUIMessages.InstallWizard2_updateOperationHasFailed, e);
ErrorDialog.openError(null, null, null, status);
}
});
}
}
return false;
}
}
return true;
} finally {
monitor.done();
}
}
private boolean retryDownload(final FeatureDownloadException e) {
final boolean retry[] = new boolean[1];
UpdateUI.getStandardDisplay().syncExec(new Runnable() {
public void run() {
retry[0] = MessageDialog.openQuestion(
UpdateUI.getActiveWorkbenchShell(),
UpdateUIMessages.InstallWizard_retryTitle,
e.getMessage()+"\n" //$NON-NLS-1$
+ UpdateUIMessages.InstallWizard_retry);
}
});
return retry[0];
}
private class UpdateJobChangeListener extends JobChangeAdapter {
public void done(final IJobChangeEvent event) {
// the job listener is triggered when the download job is done, and it proceeds
// with the actual install
if (event.getJob() == InstallWizard2.this.job && event.getResult() == Status.OK_STATUS) {
Job.getJobManager().removeJobChangeListener(this);
Job.getJobManager().cancel(job);
Job installJob = new Job(UpdateUIMessages.InstallWizard_jobName) {
public IStatus run(IProgressMonitor monitor) {
//install(monitor);
if (install(monitor)) {
return Status.OK_STATUS;
} else {
isRunning = false;
return Status.CANCEL_STATUS;
}
}
public boolean belongsTo(Object family) {
return InstallWizard2.jobFamily == family;
}
};
installJob.setUser(true);
installJob.setPriority(Job.INTERACTIVE);
// if (wait) {
// progressService.showInDialog(workbench.getActiveWorkbenchWindow().getShell(), job);
// }
installJob.schedule();
/*final IProgressService progressService= PlatformUI.getWorkbench().getProgressService();
UpdateUI.getStandardDisplay().asyncExec(new Runnable() {
public void run() {
try {
progressService.busyCursorWhile( new IRunnableWithProgress() {
public void run(final IProgressMonitor monitor){
install(monitor);
}
});
} catch (InvocationTargetException e) {
UpdateUI.logException(e);
} catch (InterruptedException e) {
UpdateUI.logException(e, false);
}
}
}); */
} else if (event.getJob() == InstallWizard2.this.job && event.getResult() != Status.OK_STATUS) {
isRunning = false;
Job.getJobManager().removeJobChangeListener(this);
Job.getJobManager().cancel(job);
UpdateUI.getStandardDisplay().syncExec(new Runnable() {
public void run() {
UpdateUI.log(event.getResult(), true);
}
});
}
}
}
public ISiteFeatureReference getFeatureReference(IFeature feature) {
ISite site = feature.getSite();
ISiteFeatureReference[] references = site.getFeatureReferences();
ISiteFeatureReference currentReference = null;
for (int i = 0; i < references.length; i++) {
currentReference = references[i];
try {
if (feature.getVersionedIdentifier().equals(currentReference.getVersionedIdentifier()))
return currentReference;
} catch (CoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
UpdateCore.warn("Feature " + feature + " not found on site" + site.getURL()); //$NON-NLS-1$ //$NON-NLS-2$
return null;
}
}