/*******************************************************************************
* Copyright (c) 2014 Mentor Graphics 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:
* Mentor Graphics - initial API and implementation
*******************************************************************************/
package com.codesourcery.internal.installer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
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.osgi.util.NLS;
import com.codesourcery.installer.IInstallConsoleProvider;
import com.codesourcery.installer.IInstallData;
import com.codesourcery.installer.IInstallDescription;
import com.codesourcery.installer.IInstallMode;
import com.codesourcery.installer.IInstallProduct;
import com.codesourcery.installer.IInstallWizardPage;
import com.codesourcery.installer.Installer;
import com.codesourcery.installer.ui.InstallWizardPage;
import com.codesourcery.internal.installer.ui.pages.ProductsPage;
import com.codesourcery.internal.installer.ui.pages.SummaryPage;
/**
* An install operation that works with the console.
*/
public class ConsoleInstallOperation extends InstallOperation {
/** End of line */
private static final String EOL = System.getProperty("line.separator");
/** Maximum number of console lines to display before pausing */
private static final int DEFAULT_CONSOLE_LINES = 25;
/** Progress monitor */
private ConsoleProgressMonitor progressMonitor = new ConsoleProgressMonitor();
/** Number of console lines to print at once */
private int maxLines = DEFAULT_CONSOLE_LINES;
/**
* Constructor
*/
public ConsoleInstallOperation() {
}
/**
* Sets the maximum number of console lines to print at once.
* If more than the maximum is printed, it will be paginated and require
* the user to press <code>ENTER</code> to continue.
*
* @param maxLines Maximum number of lines
*/
public void setMaxLines(int maxLines) {
this.maxLines = maxLines;
}
/**
* Returns the maximum number of lines to print at once.
*
* @return Maximum number of lines
*/
public int getMaxLines() {
return maxLines;
}
/**
* Returns the progress monitor to use for operations.
*
* @param installMode Install mode
* @return Progress monitor
*/
private IProgressMonitor getProgressMonitor(IInstallMode installMode) {
progressMonitor.setInstallMode(installMode);
return progressMonitor;
}
/**
* Reads input from the console.
*
* @param reader Console reader
* @return Console input or <code>null</code>
* @throws IllegalArgumentException if installation is cancelled
* @throws IOException on failure
*/
private String readConsole(BufferedReader reader) throws IllegalArgumentException, IOException {
String input = reader.readLine();
if ((input != null) && input.trim().toLowerCase().equals("exit")) {
throw new IllegalArgumentException(InstallMessages.SetupCancelled);
}
return input;
}
/**
* Prints to the console. If the number of lines provided is greater
* than the maximum allowed, the printing will be paginated.
*
* @param text Text to print
* @throws IllegalArgumentException if installation is cancelled
* @throws IOException on failure
*/
private void printConsole(String text) throws IllegalArgumentException, IOException {
BufferedReader consoleReader = null;
BufferedReader responseReader = null;
try {
consoleReader = new BufferedReader(new InputStreamReader(System.in));
responseReader = new BufferedReader(new StringReader(text));
StringBuilder output = new StringBuilder();
String responseLine;
int count = 0;
while ((responseLine = responseReader.readLine()) != null) {
output.append(responseLine);
output.append(EOL);
// Limit console text to a maximum and prompt to continue
if (++ count == getMaxLines()) {
count = 0;
System.out.print(output.toString());
System.out.println(EOL);
System.out.println(InstallMessages.ConsolePressEnter);
output = new StringBuilder();
readConsole(consoleReader);
}
}
System.out.print(output.toString());
}
finally {
if (responseReader != null) {
responseReader.close();
}
}
}
@Override
public void run() {
IStatus status = Status.OK_STATUS;
boolean firstPage = true;
try {
IInstallWizardPage[] wizardPages = Installer.getDefault().getInstallManager().getWizardPages();
IInstallData installData = Installer.getDefault().getInstallManager().getInstallData();
// Add summary page
IInstallWizardPage[] pages = new IInstallWizardPage[wizardPages.length + 2];
System.arraycopy(wizardPages, 0, pages, 0, wizardPages.length);
pages[pages.length - 2] = new SummaryPage("summaryPage", InstallMessages.SummaryPageTitle);
// Add uninstall products page
ProductsPage productsPage = new ProductsPage("productsPage", InstallMessages.ProductsPageTitle, InstallMessages.ProductsMessage);
productsPage.setMessage(InstallMessages.SelectProductsToUninstall);
pages[pages.length - 1] = productsPage;
// Show wizard pages
for (IInstallWizardPage page : pages) {
if (!page.isSupported())
continue;
// Page supports console presentation
if (page instanceof IInstallConsoleProvider) {
// Set active
page.setActive(installData);
IInstallConsoleProvider consolePage = (IInstallConsoleProvider)page;
// Get initial page text
String response = consolePage.getConsoleResponse(null);
// If this is the first page, print the exit prompt
if (firstPage) {
firstPage = false;
response = InstallMessages.ConsoleExitPrompt + response;
}
while (response != null) {
printConsole(EOL);
// Print response
printConsole(response);
// Console input reader
BufferedReader consoleReader = new BufferedReader(new InputStreamReader(System.in));
// Get input
String input = readConsole(consoleReader);
if (input == null)
break;
// Get page next response
response = consolePage.getConsoleResponse(input);
// Save page data
if (response == null) {
try {
page.saveInstallData(installData);
}
catch (CoreException e) {
printConsole(e.getStatus().getMessage());
// Start page over
response = consolePage.getConsoleResponse(null);
}
}
}
}
}
IInstallMode installMode = Installer.getDefault().getInstallManager().getInstallMode();
// Install
if (installMode.isInstall()) {
Installer.getDefault().getInstallManager().install(getProgressMonitor(installMode));
try {
printConsole(EOL);
// Mirror
if (Installer.getDefault().getInstallManager().getInstallMode().isMirror()) {
printConsole(NLS.bind(InstallMessages.ConsoleMirrorComplete0, getInstallManager().getInstallDescription().getProductName()));
}
// Install
else {
printConsole(NLS.bind(InstallMessages.ConsoleInstallationComplete0, getInstallManager().getInstallDescription().getProductName()));
}
String installText = getInstallManager().getInstallDescription().getText(IInstallDescription.TEXT_INSTALL_ADDENDUM, null);
if (installText != null) {
printConsole(EOL);
printConsole(InstallWizardPage.formatConsoleMessage(installText));
}
}
catch (Exception e) {
Installer.log(e);
}
}
// Uninstall
else {
IInstallProduct[] products = productsPage.getSelectedProducts();
if (products.length > 0) {
Installer.getDefault().getInstallManager().uninstall(products, getProgressMonitor(installMode));
printConsole(EOL);
printConsole(InstallMessages.ConsoleUninstallationComplete);
try {
for (IInstallProduct product : products) {
String uninstallText = product.getProperty(IInstallProduct.PROPERTY_UNINSTALL_TEXT);
if (uninstallText != null) {
printConsole(InstallWizardPage.formatConsoleMessage(uninstallText));
}
}
}
catch (Exception e) {
Installer.log(e);;
}
}
}
}
// Install aborted
catch (IllegalArgumentException e) {
status = new Status(IStatus.CANCEL, Installer.ID, 0, e.getLocalizedMessage(), null);
showError(e.getMessage());
cleanupInstallation();
}
catch (Exception e) {
status = new Status(IStatus.ERROR, Installer.ID, 0, e.getLocalizedMessage(), e);
Installer.log(e);
showError(e.getLocalizedMessage());
cleanupInstallation();
}
// Write status
writeStatus(status);
}
/**
* Console progress monitor
*/
class ConsoleProgressMonitor implements IProgressMonitor {
private boolean canceled;
private IInstallMode installMode;
/**
* Constructor
*/
public ConsoleProgressMonitor() {
}
/**
* Sets the install mode.
*
* @param installMode Install mode
*/
public void setInstallMode(IInstallMode installMode) {
this.installMode = installMode;
}
/**
* @return The install mode.
*/
private IInstallMode getInstallMode() {
return installMode;
}
@Override
public void beginTask(String name, int totalWork) {
System.out.print(getInstallMode().isInstall() ?
(getInstallMode().isMirror() ? InstallMessages.ConsoleSaving : InstallMessages.ConsoleInstalling) :
InstallMessages.ConsoleUninstalling);
}
@Override
public void done() {
System.out.print(EOL);
}
@Override
public void internalWorked(double work) {
// Append progress tick
System.out.print('.');
}
@Override
public boolean isCanceled() {
return canceled;
}
@Override
public void setCanceled(boolean value) {
canceled = value;
}
@Override
public void setTaskName(String name) {
}
@Override
public void subTask(String name) {
}
@Override
public void worked(int work) {
}
}
@Override
public void showError(String message) {
System.err.println(message);
}
}