Java tutorial
/* * Copyright (c) 2014, 2015 Eike Stepper (Berlin, Germany) 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: * Eike Stepper - initial API and implementation * Yatta Solutions - [466264] Enhance UX in simple installer */ package org.eclipse.oomph.setup.internal.installer; import org.eclipse.oomph.internal.setup.SetupProperties; import org.eclipse.oomph.jreinfo.JREManager; import org.eclipse.oomph.p2.core.P2Util; import org.eclipse.oomph.p2.core.ProfileTransaction.Resolution; import org.eclipse.oomph.setup.internal.core.SetupContext; import org.eclipse.oomph.setup.ui.AbstractSetupDialog; import org.eclipse.oomph.setup.ui.wizards.SetupWizard.SelectionMemento; import org.eclipse.oomph.ui.ErrorDialog; import org.eclipse.oomph.ui.UIUtil; import org.eclipse.oomph.util.IOUtil; import org.eclipse.oomph.util.OomphPlugin.Preference; import org.eclipse.oomph.util.PropertiesUtil; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.equinox.app.IApplication; import org.eclipse.equinox.app.IApplicationContext; import org.eclipse.equinox.p2.core.IProvisioningAgent; import org.eclipse.equinox.p2.core.UIServices; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.window.Window; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.util.concurrent.atomic.AtomicInteger; /** * @author Eike Stepper */ public class InstallerApplication implements IApplication { public static final Integer EXIT_ERROR = 1; private static final Preference PREF_MODE = SetupInstallerPlugin.INSTANCE.getConfigurationPreference("mode"); private static final boolean SKIP_COCOA_MENU = PropertiesUtil.isProperty("oomph.cocoa.menu.skip"); private Mode mode = Mode.SIMPLE; protected Integer run(final IApplicationContext context) throws Exception { // This must come very early, before the first model is accessed, so that HTTPS can be authorized. P2Util.getCurrentProvisioningAgent().registerService(UIServices.SERVICE_NAME, Installer.SERVICE_UI); @SuppressWarnings("restriction") IProvisioningAgent agent = (IProvisioningAgent) org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper .getService(org.eclipse.equinox.internal.p2.repository.Activator.getContext(), IProvisioningAgent.SERVICE_NAME); agent.registerService(UIServices.SERVICE_NAME, Installer.SERVICE_UI); final InstallerUI[] installerDialog = { null }; Thread jreInitializer = new Thread("JRE Initializer") { @Override public void run() { JREManager.INSTANCE.getJREs(); for (;;) { InstallerUI installerUI = installerDialog[0]; if (installerUI != null) { installerUI.refreshJREs(); break; } try { sleep(100); } catch (InterruptedException ex) { return; } } } }; jreInitializer.setDaemon(true); jreInitializer.start(); int[] sizes = { 16, 32, 48, 64, 128, 256 }; Image[] images = new Image[sizes.length]; for (int i = 0; i < sizes.length; i++) { int size = sizes[i]; images[i] = SetupInstallerPlugin.INSTANCE.getSWTImage("oomph" + size + ".png"); } Window.setDefaultImages(images); boolean restarted = false; File restarting = new File( SetupContext.CONFIGURATION_STATE_LOCATION_URI.appendSegment("restarting").toFileString()); SelectionMemento selectionMemento = null; if (restarting.exists()) { try { restarted = true; selectionMemento = (SelectionMemento) IOUtil.readObject(restarting, getClass().getClassLoader()); } catch (Throwable ex) { //$FALL-THROUGH$ } finally { try { restarting.delete(); } catch (Throwable ex) { //$FALL-THROUGH$ } } } final Display display = Display.getDefault(); Display.setAppName(AbstractSetupDialog.SHELL_TEXT); handleCocoaMenu(display, installerDialog); if (context != null) { display.asyncExec(new Runnable() { public void run() { // End the splash screen once the dialog is up. context.applicationRunning(); } }); } String modeName = PropertiesUtil.getProperty(SetupProperties.PROP_SETUP_INSTALLER_MODE); if (modeName == null) { modeName = PREF_MODE.get(Mode.SIMPLE.name()); } mode = Mode.valueOf(modeName.toUpperCase()); for (;;) { if (selectionMemento == null) { selectionMemento = new SelectionMemento(); } Installer installer = new Installer(selectionMemento); if (mode == Mode.ADVANCED) { if (KeepInstallerUtil.canKeepInstaller()) { Shell shell = new Shell(display); if (MessageDialog.openQuestion(shell, AbstractSetupDialog.SHELL_TEXT, "As an advanced user, do you want to keep the installer in a permanent location?")) { if (new KeepInstallerDialog(shell, true).open() == KeepInstallerDialog.OK) { return EXIT_OK; } } } installerDialog[0] = new InstallerDialog(null, installer, restarted); } else { SimpleInstallerDialog dialog = new SimpleInstallerDialog(display, installer, restarted); installer.setSimpleShell(dialog); installerDialog[0] = dialog; } final int retcode = installerDialog[0].show(); if (retcode == InstallerUI.RETURN_SIMPLE) { setMode(Mode.SIMPLE); selectionMemento = null; continue; } if (retcode == InstallerUI.RETURN_ADVANCED) { setMode(Mode.ADVANCED); selectionMemento = null; continue; } if (retcode == InstallerUI.RETURN_RESTART) { try { IOUtil.writeObject(restarting, selectionMemento); } catch (Throwable ex) { //$FALL-THROUGH$ } String launcher = getLauncher(); if (launcher != null) { try { // EXIT_RESTART often makes the new process come up behind other windows, so try a fresh native process first. Runtime.getRuntime().exec(launcher); return EXIT_OK; } catch (Throwable ex) { //$FALL-THROUGH$ } } return EXIT_RESTART; } return EXIT_OK; } } private void setMode(Mode mode) { this.mode = mode; PREF_MODE.set(mode.name()); } private void handleCocoaMenu(final Display display, final InstallerUI[] installerDialog) { if (!SKIP_COCOA_MENU && Platform.WS_COCOA.equals(Platform.getWS())) { Runnable about = new Runnable() { public void run() { if (installerDialog[0] != null) { installerDialog[0].showAbout(); } } }; Runnable preferences = new Runnable() { public void run() { if (installerDialog[0] != null) { NetworkConnectionsDialog proxyPreferenceDialog = new NetworkConnectionsDialog( installerDialog[0].getShell()); proxyPreferenceDialog.open(); } } }; Runnable quit = new Runnable() { public void run() { if (installerDialog[0] != null) { display.dispose(); } } }; CocoaUtil.register(display, about, preferences, quit); } } public Object start(IApplicationContext context) throws Exception { try { return run(context); } catch (Throwable t) { SetupInstallerPlugin.INSTANCE.log(t); final AtomicInteger exitCode = new AtomicInteger(EXIT_ERROR); ErrorDialog dialog = new ErrorDialog("Error", t, 0, 2, IDialogConstants.OK_LABEL, "Update", IDialogConstants.SHOW_DETAILS_LABEL) { @Override protected void buttonPressed(int buttonId) { super.buttonPressed(buttonId); if (buttonId == 1) { update(); } } private void update() { try { final Shell shell = getShell(); if (!MessageDialog.openQuestion(shell, "Emergency Update", "This is an emergency update. Continue?\n\n" + "To lower the risk of problems during this update it will be implied that you accept new licenses or unsigned content.")) { return; } ProgressMonitorDialog dialog = new ProgressMonitorDialog(shell) { @Override protected Point getInitialSize() { Point calculatedSize = super.getInitialSize(); if (calculatedSize.x < 800) { calculatedSize.x = 800; } return calculatedSize; } }; try { dialog.run(true, true, new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { SubMonitor progress = SubMonitor.convert(monitor, 2); try { Resolution resolution = SelfUpdate.resolve(null, progress.newChild(1)); if (resolution == null) { UIUtil.syncExec(new Runnable() { public void run() { MessageDialog.openInformation(shell, "Update", "No updates were found."); } }); return; } resolution.commit(progress.newChild(1)); exitCode.set(EXIT_RESTART); } catch (Throwable ex) { throw new InvocationTargetException(ex); } finally { progress.done(); } } }); } catch (OperationCanceledException ex) { //$FALL-THROUGH$ } catch (InvocationTargetException ex) { if (!(ex.getCause() instanceof OperationCanceledException)) { throw ex; } } } catch (Throwable ex) { SetupInstallerPlugin.INSTANCE.log(ex); ErrorDialog.open(ex); } } }; dialog.open(); return exitCode.get(); } } public void stop() { // Do nothing. } public static String getLauncher() { try { String launcher = PropertiesUtil.getProperty("eclipse.launcher"); if (launcher != null && new File(launcher).isFile()) { return launcher; } } catch (Throwable ex) { ex.printStackTrace(); //$FALL-THROUGH$ } return null; } /** * @author Eike Stepper */ public static enum Mode { SIMPLE, ADVANCED; } }