| /******************************************************************************* |
| * Copyright (c) 2000, 2005 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.Platform; |
| 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.operation.IRunnableWithProgress; |
| import org.eclipse.jface.wizard.IWizardPage; |
| import org.eclipse.jface.wizard.Wizard; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.progress.IProgressService; |
| 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.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.UpdateCore; |
| import org.eclipse.update.internal.operations.DuplicateConflictsValidator; |
| 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 (Platform.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); |
| 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 || Platform.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) |
| Platform.getJobManager().removeJobChangeListener(jobListener); |
| if (job != null) |
| Platform.getJobManager().cancel(job); |
| jobListener = new UpdateJobChangeListener(); |
| Platform.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 void 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); |
| } |
| }); |
| } |
| } catch (CoreException e) { |
| } finally { |
| isRunning = false; |
| } |
| } |
| |
| 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, 3*ops.length); |
| for (int i=0; i<ops.length; i++) { |
| IInstallFeatureOperation op = (IInstallFeatureOperation)ops[i]; |
| SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, 3); |
| try { |
| 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); |
| Display.getDefault().syncExec( new Runnable () { |
| public void run() { |
| IStatus status = new Status( IStatus.ERROR, UpdateUI.getPluginId(), IStatus.OK, UpdateUIMessages.InstallWizard2_updateOperationHasFailed, null); |
| 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) { |
| Platform.getJobManager().removeJobChangeListener(this); |
| Platform.getJobManager().cancel(job); |
| |
| 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; |
| Platform.getJobManager().removeJobChangeListener(this); |
| Platform.getJobManager().cancel(job); |
| UpdateUI.getStandardDisplay().syncExec(new Runnable() { |
| public void run() { |
| UpdateUI.log(event.getResult(), true); |
| } |
| }); |
| } |
| } |
| } |
| |
| } |