/*************************************************************************** * * * ConsoleThread.java * * ------------------- * * date : 16. Mai 2003, 18:27 * * copyright : (C) 2004 Distributed and Mobile Systems Group * * Lehrstuhl fuer Praktische Informatik * * Universitaet Bamberg * * http://www.uni-bamberg.de/pi/ * * email : sven.kaffille@uni-bamberg.de * * * * * ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * A copy of the license can be found in the license.txt file supplied * * with this software or at: http://www.gnu.org/copyleft/gpl.html * * * ***************************************************************************/ package de.uniba.wiai.lspi.util.console; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.io.OutputStream; import de.uniba.wiai.lspi.util.console.parser.CommandParser; import de.uniba.wiai.lspi.util.console.parser.ParseException; import de.uniba.wiai.lspi.util.console.parser.TokenMgrError; /** * @author sven * @version 1.0.5 */ public class ConsoleThread extends Thread { /** * Reference to the only instance of this. */ static ConsoleThread console; /** * The name of this console. Displayed before any input. */ protected String consoleName; /** * The factory responsible for Creation of commands. */ protected CommandFactory factory; /** * The text displayed, when the Thread is started. */ protected String welcome = "Welcome!"; /** * The {@link Command} that exits the console. Its execute method is invoked * and the console exits. */ protected Command exitCommand; /** * The PrintStream to print the consoles output to. */ protected PrintStream out; /** * The old PrintStream to print the standard output to. Is <code>null</code> * if this console does not change the standard output via constructor * {@link #ConsoleThread(String, CommandFactory)}. */ protected PrintStream systemOut = null; /** * Reference to the standard output stream. */ protected OutputStream systemOutputStream = null; /** * Creates a new instance of ConsoleThread * * @param name * The name of this console. Displayed before any input. * @param f * The {@link CommandFactory} responsible for creating * {@link Command}s. */ protected ConsoleThread(String name, CommandFactory f) { super("Console-" + name); this.consoleName = name; this.factory = f; this.out = f.getPrintStream(); } /** * Creates a new instance of ConsoleThread. The standard output * {@link System#out} is redirected to <code>systemOut</code>. * * @param name * The name of this console. Displayed before any input. * @param f * The {@link CommandFactory} responsible for creating * {@link Command}s. * @param systemOut * The {@link OutputStream} to redirect standard ouput to. If you * do not want to have any output send to System.out, you can use * {@link DummyOutputStream}. If you want to save output send to * System.out in Memory to e.g. display it later you can use * {@link MemoryOutputStream}. To write output to a file you can * use {@link java.io.FileOutputStream}. */ protected ConsoleThread(String name, CommandFactory f, OutputStream systemOut) { this(name, f); /* save System.out to restore it when this console thread is stopped. */ this.systemOut = System.out; this.systemOutputStream = systemOut; System.setOut(new PrintStream(this.systemOutputStream)); } /** * Method to obtain a reference to the console currently active in this JVM. * Returns <code>null</code>, if there is none. * * @return Reference to the singleton console thread. */ public static ConsoleThread getConsole() { return console; } /** * Factory method to get a reference to the console singleton. Creates a new * instance if there is no console in the JVM. If there is currently one * console the arguments provided to this method have no effect. * * @param name * @param factory * @return Reference to the singleton console thread. */ public static ConsoleThread getConsole(String name, CommandFactory factory) { if (console == null) { console = new ConsoleThread(name, factory); } return console; } /** * Factory method to create a console. Creates a new instance if there is no * console in the JVM. If there is currently one console the arguments * provided to this method have no effect. * * @param name * @param factory * @param systemOut * @return Reference to the singleton console thread. */ public static ConsoleThread getConsole(String name, CommandFactory factory, OutputStream systemOut) { if (console == null) { console = new ConsoleThread(name, factory, systemOut); } return console; } /** * Get a reference to the {@link PrintStream} this console prints its output * to. * * @return Reference to the {@link PrintStream} this console prints its * output to. */ public PrintStream getPrintStream() { return this.out; } /** * Get a reference to the {@link OutputStream} calls to System.out are * delegated to. Returns <code>null</code> if System.out has not been * redirected. * * @return Reference to the {@link OutputStream} calls to System.out are * delegated to. Returns <code>null</code> if System.out has not * been redirected. */ public OutputStream getSystemOutputStream() { return this.systemOutputStream; } /** * Get a reference to the {@link CommandFactory} used by this console. * * @return Reference to the {@link CommandFactory} used by this console. */ public CommandFactory getCommandFactory() { return this.factory; } /** * Set a costum welcome text for the console. * * @param text * The welcome text to set. */ public void setWelcomeText(String text) { this.welcome = text; } /** * The run method. Loops until the exitCommand has been invoked. */ public void run() { this.out.println(this.welcome); boolean running = true; this.out.println("Console ready. "); while (running) { this.out.print(this.consoleName + " > "); try { BufferedReader reader = new BufferedReader( new InputStreamReader(System.in)); String command = reader.readLine(); if (command == null) { command = ""; } command = command.trim(); if (!command.equals("")) { String c = CommandParser.parse(command); if ((this.exitCommand != null) && (c.equalsIgnoreCase(this.exitCommand .getCommandName()))) { this.out.println("Exiting " + this.consoleName + "..."); Command com = this.factory.createCommand(command); this.out.print("Do you really want to shutdown? "); String answer = ""; while ((answer == null) || (answer.length() == 0)) { try { answer = reader.readLine(); } catch (IOException e) { answer = ""; } if ( (answer != null) && ((answer.equalsIgnoreCase("Yes")) || (answer.equalsIgnoreCase("Y")))) { com.execute(); running = false; } } } else { try { Command com = this.factory.createCommand(command); com.execute(); } catch (ConsoleException e) { this.out.println(e.getMessage()); // e.printStackTrace(out); } } } } catch (TokenMgrError tme) { this.out.println("Could not parse command."); this.out.println(tme.getMessage()); } catch (ParseException pe) { this.out.println("Could not parse command."); this.out.println(pe.getMessage()); } catch (Throwable t) { t.printStackTrace(); this.out .println("An unexpected Exception occured. Could not execute command. Reason: "); this.out.println(t.getMessage()); } } this.out.println("Shutting down."); /* restore System.out */ System.setOut(System.out); } /** * Set the {@link Command} that exits this console. Uses the * {@link CommandFactory} to create an instance of the Command. * * @param commandName * The name of the command. * @throws ConsoleException * Exception during creation of the command. */ public void setExitCommand(String commandName) throws ConsoleException { this.exitCommand = this.factory.createCommand(commandName); } }