| /* |
| * Copyright (c) 2014-2016 Eike Stepper (Loehne, Germany) and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v2.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v20.html |
| * |
| * Contributors: |
| * Eike Stepper - initial API and implementation |
| */ |
| package org.eclipse.oomph.setup.internal.installer; |
| |
| import org.eclipse.oomph.internal.ui.AccessUtil; |
| import org.eclipse.oomph.internal.ui.UIPlugin; |
| import org.eclipse.oomph.p2.core.P2Util; |
| import org.eclipse.oomph.p2.core.ProfileTransaction.Resolution; |
| import org.eclipse.oomph.setup.User; |
| import org.eclipse.oomph.setup.internal.core.SetupTaskPerformer; |
| import org.eclipse.oomph.setup.internal.installer.Installer.MissingIndexStatus; |
| import org.eclipse.oomph.setup.ui.wizards.ConfirmationPage; |
| import org.eclipse.oomph.setup.ui.wizards.SetupWizard.SelectionMemento; |
| import org.eclipse.oomph.setup.ui.wizards.SetupWizardDialog; |
| import org.eclipse.oomph.util.ExceptionHandler; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.equinox.p2.core.UIServices; |
| import org.eclipse.jface.dialogs.Dialog; |
| import org.eclipse.jface.dialogs.IDialogSettings; |
| import org.eclipse.jface.dialogs.IPageChangedListener; |
| import org.eclipse.jface.dialogs.PageChangedEvent; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.events.TraverseEvent; |
| import org.eclipse.swt.events.TraverseListener; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Link; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.ToolBar; |
| import org.eclipse.swt.widgets.ToolItem; |
| |
| /** |
| * @author Eike Stepper |
| */ |
| public final class InstallerDialog extends SetupWizardDialog implements InstallerUI |
| { |
| private final IPageChangedListener pageChangedListener = new PageChangedListener(); |
| |
| private final boolean restarted; |
| |
| private ToolItem updateToolItem; |
| |
| private boolean updateSearching; |
| |
| private Resolution updateResolution; |
| |
| private IStatus updateError; |
| |
| private String version; |
| |
| private Link versionLink; |
| |
| /** |
| * Used only in the generated documentation. |
| */ |
| public InstallerDialog(Shell parentShell, boolean restarted) |
| { |
| this(parentShell, new Installer(new SelectionMemento(), P2Util.getCurrentProvisioningAgent().getService(UIServices.class)), restarted); |
| } |
| |
| public InstallerDialog(Shell parentShell, Installer installer, boolean restarted) |
| { |
| super(parentShell, installer); |
| this.restarted = restarted; |
| addPageChangedListener(pageChangedListener); |
| |
| if (UIPlugin.isRecorderEnabled()) |
| { |
| setNonModal(); |
| } |
| } |
| |
| public Installer getInstaller() |
| { |
| return (Installer)getWizard(); |
| } |
| |
| @Override |
| public boolean refreshJREs() |
| { |
| ProductPage page = (ProductPage)getWizard().getPage(ProductPage.PAGE_NAME); |
| if (page != null) |
| { |
| return page.refreshJREs(); |
| } |
| |
| return false; |
| } |
| |
| @Override |
| public void create() |
| { |
| super.create(); |
| |
| final Shell shell = getShell(); |
| shell.addTraverseListener(new TraverseListener() |
| { |
| @Override |
| public void keyTraversed(TraverseEvent e) |
| { |
| if (e.detail == SWT.TRAVERSE_ESCAPE) |
| { |
| shell.close(); |
| e.detail = SWT.TRAVERSE_NONE; |
| e.doit = false; |
| } |
| } |
| }); |
| |
| shell.getDisplay().asyncExec(new Runnable() |
| { |
| @Override |
| public void run() |
| { |
| final Installer installer = getInstaller(); |
| if (!shell.isDisposed()) |
| { |
| final Runnable checkIndex = this; |
| shell.getDisplay().asyncExec(new Runnable() |
| { |
| @Override |
| public void run() |
| { |
| if (!shell.isDisposed()) |
| { |
| installer.getIndexLoader().awaitIndexLoad(); |
| |
| UIPlugin.openRecorderIfEnabled(); |
| SetupInstallerPlugin.runTests(); |
| |
| if (installer.getCatalogManager().getIndex() == null) |
| { |
| MissingIndexStatus missingIndexStatus = installer.handleMissingIndex(shell); |
| switch (missingIndexStatus) |
| { |
| case EXIT: |
| { |
| close(); |
| break; |
| } |
| case RETRY: |
| { |
| shell.getDisplay().asyncExec(checkIndex); |
| break; |
| } |
| default: |
| { |
| // Ignore. |
| break; |
| } |
| } |
| } |
| } |
| } |
| }); |
| } |
| } |
| }); |
| } |
| |
| @Override |
| protected Control createHelpControl(Composite parent) |
| { |
| Control helpControl = super.createHelpControl(parent); |
| setProductVersionLink(parent); |
| return helpControl; |
| } |
| |
| @Override |
| protected void createToolItemsForToolBar(ToolBar toolBar) |
| { |
| ToolItem networkProxySettingsToolItem = createToolItem(toolBar, "install_prefs_proxy.png", Messages.InstallerDialog_NetProxy_message); //$NON-NLS-1$ |
| networkProxySettingsToolItem.addSelectionListener(new SelectionAdapter() |
| { |
| @Override |
| public void widgetSelected(SelectionEvent e) |
| { |
| Dialog dialog = new NetworkConnectionsDialog(getShell()); |
| dialog.open(); |
| } |
| }); |
| AccessUtil.setKey(networkProxySettingsToolItem, "proxy"); //$NON-NLS-1$ |
| |
| ToolItem sshSettingsToolItem = createToolItem(toolBar, "install_prefs_ssh2.png", Messages.InstallerDialog_SSH2_message); //$NON-NLS-1$ |
| sshSettingsToolItem.addSelectionListener(new SelectionAdapter() |
| { |
| @Override |
| public void widgetSelected(SelectionEvent e) |
| { |
| Dialog dialog = new NetworkSSH2Dialog(getShell()); |
| dialog.open(); |
| } |
| }); |
| AccessUtil.setKey(sshSettingsToolItem, "ssh"); //$NON-NLS-1$ |
| |
| ToolItem trustSettingsToolItem = createToolItem(toolBar, "trust.png", Messages.InstallerDialog_TrustSettings_message); //$NON-NLS-1$ |
| trustSettingsToolItem.addSelectionListener(new SelectionAdapter() |
| { |
| @Override |
| public void widgetSelected(SelectionEvent e) |
| { |
| Dialog dialog = new TrustDialog(getShell()); |
| dialog.open(); |
| } |
| }); |
| AccessUtil.setKey(trustSettingsToolItem, "trust"); //$NON-NLS-1$ |
| |
| ToolItem simpleToolItem = createToolItem(toolBar, "simple.png", Messages.InstallerDialog_SwitchToSimpleModel_message); //$NON-NLS-1$ |
| simpleToolItem.addSelectionListener(new SelectionAdapter() |
| { |
| @Override |
| public void widgetSelected(SelectionEvent e) |
| { |
| close(); |
| setReturnCode(RETURN_SIMPLE); |
| } |
| }); |
| AccessUtil.setKey(simpleToolItem, "simple"); //$NON-NLS-1$ |
| |
| final ToolItem webLinksToolItem = createToolItem(toolBar, URISchemeUtil.isRegistered() ? "web_links_registered.png" : "web_links_unregistered.png", //$NON-NLS-1$ //$NON-NLS-2$ |
| SimpleInstallerDialog.WEB_LINKS_MENU_ITEM_DESCRIPTION); |
| webLinksToolItem.addSelectionListener(new SelectionAdapter() |
| { |
| @Override |
| public void widgetSelected(SelectionEvent e) |
| { |
| if (URISchemeUtil.manageRegistrations(getShell()) == URISchemeUtil.RegistrationConfirmation.KEEP_INSTALLER) |
| { |
| KeepInstallerDialog keepInstallerDialog = new KeepInstallerDialog(getShell(), true); |
| if (keepInstallerDialog.open() == Window.OK) |
| { |
| close(); |
| return; |
| } |
| } |
| |
| webLinksToolItem |
| .setImage(SetupInstallerPlugin.INSTANCE.getSWTImage(URISchemeUtil.isRegistered() ? "web_links_registered.png" : "web_links_unregistered.png")); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| }); |
| AccessUtil.setKey(simpleToolItem, "web-links"); //$NON-NLS-1$ |
| |
| updateToolItem = createToolItem(toolBar, "install_update0.png", Messages.InstallerDialog_Update_message); //$NON-NLS-1$ |
| updateToolItem.setDisabledImage(SetupInstallerPlugin.INSTANCE.getSWTImage("install_searching0.png")); //$NON-NLS-1$ |
| updateToolItem.addSelectionListener(new SelectionAdapter() |
| { |
| @Override |
| public void widgetSelected(SelectionEvent e) |
| { |
| selfUpdate(); |
| } |
| }); |
| AccessUtil.setKey(updateToolItem, "update"); //$NON-NLS-1$ |
| } |
| |
| protected final ToolItem createToolItem(ToolBar toolBar, String iconPath, String toolTip) |
| { |
| ToolItem toolItem = new ToolItem(toolBar, SWT.PUSH); |
| if (iconPath == null) |
| { |
| toolItem.setText(toolTip); |
| } |
| else |
| { |
| Image image = SetupInstallerPlugin.INSTANCE.getSWTImage(iconPath); |
| toolItem.setImage(image); |
| toolItem.setToolTipText(toolTip); |
| } |
| |
| return toolItem; |
| } |
| |
| private void selfUpdate() |
| { |
| updateError = null; |
| setUpdateIcon(0); |
| |
| if (updateResolution == null) |
| { |
| initUpdateSearch(); |
| } |
| else |
| { |
| Runnable successRunnable = new Runnable() |
| { |
| @Override |
| public void run() |
| { |
| restart(); |
| } |
| }; |
| |
| ExceptionHandler<CoreException> exceptionHandler = new ExceptionHandler<>() |
| { |
| @Override |
| public void handleException(CoreException ex) |
| { |
| updateError = ex.getStatus(); |
| } |
| }; |
| |
| Runnable finalRunnable = new Runnable() |
| { |
| @Override |
| public void run() |
| { |
| updateResolution = null; |
| setUpdateIcon(0); |
| } |
| }; |
| |
| SelfUpdate.update(getShell(), updateResolution, successRunnable, exceptionHandler, finalRunnable); |
| } |
| } |
| |
| private void initUpdateSearch() |
| { |
| updateSearching = true; |
| |
| Thread updateIconSetter = new UpdateIconAnimator(); |
| updateIconSetter.start(); |
| |
| Thread updateSearcher = new UpdateSearcher(); |
| updateSearcher.start(); |
| } |
| |
| private void setUpdateIcon(final int icon) |
| { |
| if (!updateToolItem.isDisposed()) |
| { |
| updateToolItem.getDisplay().asyncExec(new Runnable() |
| { |
| @Override |
| public void run() |
| { |
| if (updateToolItem == null || updateToolItem.isDisposed()) |
| { |
| return; |
| } |
| |
| try |
| { |
| if (updateSearching) |
| { |
| updateToolItem.setToolTipText(Messages.InstallerDialog_CheckForUpdates_message); |
| updateToolItem.setDisabledImage(SetupInstallerPlugin.INSTANCE.getSWTImage("install_searching" + icon + ".png")); //$NON-NLS-1$ //$NON-NLS-2$ |
| updateToolItem.setEnabled(false); |
| } |
| else if (updateError != null) |
| { |
| StringBuilder builder = new StringBuilder(); |
| formatStatus(builder, "", updateError); //$NON-NLS-1$ |
| updateToolItem.setToolTipText(builder.toString()); |
| updateToolItem.setImage(SetupInstallerPlugin.INSTANCE.getSWTImage("install_error.png")); //$NON-NLS-1$ |
| updateToolItem.setEnabled(true); |
| } |
| else if (updateResolution != null) |
| { |
| updateToolItem.setToolTipText(Messages.InstallerDialog_InstallUpdates_message); |
| updateToolItem.setImage(SetupInstallerPlugin.INSTANCE.getSWTImage("install_update" + icon + ".png")); //$NON-NLS-1$ //$NON-NLS-2$ |
| updateToolItem.setEnabled(true); |
| } |
| else |
| { |
| updateToolItem.setToolTipText(Messages.InstallerDialog_NoUpdates_message); |
| updateToolItem.setDisabledImage(SetupInstallerPlugin.INSTANCE.getSWTImage("install_update_disabled.png")); //$NON-NLS-1$ |
| updateToolItem.setEnabled(false); |
| } |
| } |
| catch (Exception ex) |
| { |
| // Ignore |
| } |
| } |
| |
| private void formatStatus(StringBuilder builder, String indent, IStatus status) |
| { |
| if (builder.length() != 0) |
| { |
| builder.append('\n'); |
| } |
| |
| builder.append(indent); |
| builder.append(status.getMessage()); |
| |
| for (IStatus child : status.getChildren()) |
| { |
| formatStatus(builder, indent + " ", child); //$NON-NLS-1$ |
| } |
| } |
| }); |
| } |
| } |
| |
| private void setProductVersionLink(Composite parent) |
| { |
| GridLayout parentLayout = (GridLayout)parent.getLayout(); |
| parentLayout.numColumns++; |
| parentLayout.horizontalSpacing = 10; |
| |
| versionLink = new Link(parent, SWT.NO_FOCUS); |
| versionLink.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_CENTER | GridData.VERTICAL_ALIGN_CENTER)); |
| versionLink.setToolTipText(Messages.InstallerDialog_About_message); |
| versionLink.setText("<a>0.0.0</a>"); //$NON-NLS-1$ |
| AccessUtil.setKey(versionLink, "version"); //$NON-NLS-1$ |
| |
| Thread thread = new ProductVersionInitializer(); |
| thread.start(); |
| } |
| |
| @Override |
| public int show() |
| { |
| setBlockOnOpen(false); |
| open(); |
| |
| getInstaller().runEventLoop(getShell()); |
| |
| return getReturnCode(); |
| } |
| |
| @Override |
| public void showAbout() |
| { |
| new AboutDialog(getShell(), version).open(); |
| } |
| |
| public void restart() |
| { |
| close(); |
| setReturnCode(RETURN_RESTART); |
| } |
| |
| public void reset() |
| { |
| close(); |
| setReturnCode(RETURN_ADVANCED); |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private final class PageChangedListener implements IPageChangedListener |
| { |
| @Override |
| public void pageChanged(PageChangedEvent event) |
| { |
| if (event.getSelectedPage() instanceof ConfirmationPage) |
| { |
| updateSearching = false; |
| updateResolution = null; |
| updateError = null; |
| setUpdateIcon(0); |
| |
| SetupTaskPerformer performer = getInstaller().getPerformer(); |
| performer.getBundles().add(SetupInstallerPlugin.INSTANCE.getBundle()); |
| } |
| } |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private final class ProductVersionInitializer extends Thread |
| { |
| public ProductVersionInitializer() |
| { |
| super(Messages.InstallerDialog_ProductVersionInitializer_thread); |
| } |
| |
| @Override |
| public void run() |
| { |
| try |
| { |
| version = SelfUpdate.getProductVersion(); |
| if (version != null) |
| { |
| if (version == SelfUpdate.SELF_HOSTING) |
| { |
| updateSearching = false; |
| setUpdateIcon(0); |
| } |
| else if (!restarted) |
| { |
| initUpdateSearch(); |
| } |
| |
| versionLink.getDisplay().asyncExec(new Runnable() |
| { |
| @Override |
| public void run() |
| { |
| try |
| { |
| versionLink.addSelectionListener(new SelectionAdapter() |
| { |
| @Override |
| public void widgetSelected(SelectionEvent e) |
| { |
| showAbout(); |
| } |
| }); |
| |
| versionLink.setText("<a>" + version + "</a>"); //$NON-NLS-1$ //$NON-NLS-2$ |
| versionLink.getParent().layout(); |
| } |
| catch (Exception ex) |
| { |
| SetupInstallerPlugin.INSTANCE.log(ex); |
| } |
| } |
| }); |
| } |
| } |
| catch (Exception ex) |
| { |
| SetupInstallerPlugin.INSTANCE.log(ex); |
| } |
| } |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private final class UpdateIconAnimator extends Thread |
| { |
| public UpdateIconAnimator() |
| { |
| super(Messages.InstallerDialog_UpdateIconAnimator_thread); |
| } |
| |
| @Override |
| public void run() |
| { |
| try |
| { |
| for (int i = 0; updateSearching || updateResolution != null; i = ++i % 20) |
| { |
| if (updateToolItem == null || updateToolItem.isDisposed()) |
| { |
| return; |
| } |
| |
| int icon = i > 7 ? 0 : i; |
| setUpdateIcon(icon); |
| sleep(80); |
| } |
| |
| setUpdateIcon(0); |
| } |
| catch (Exception ex) |
| { |
| SetupInstallerPlugin.INSTANCE.log(ex); |
| } |
| } |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private final class UpdateSearcher extends Thread |
| { |
| public UpdateSearcher() |
| { |
| super(Messages.InstallerDialog_UpdateSearcher_thread); |
| } |
| |
| @Override |
| public void run() |
| { |
| try |
| { |
| User user = getInstaller().getUser(); |
| updateResolution = SelfUpdate.resolve(user, null); |
| } |
| catch (CoreException ex) |
| { |
| updateError = ex.getStatus(); |
| } |
| finally |
| { |
| updateSearching = false; |
| } |
| } |
| } |
| |
| @Override |
| protected IDialogSettings getDialogBoundsSettings() |
| { |
| return SetupInstallerPlugin.INSTANCE.getDialogSettings("AdvancedInstaller"); //$NON-NLS-1$ |
| } |
| |
| @Override |
| protected Point basicGetInitialSize() |
| { |
| Point computedSize = super.basicGetInitialSize(); |
| computedSize.x = computedSize.x * 21 / 20; |
| return computedSize; |
| } |
| } |