1 /* 2 * $Id: ConsoleThread.java 178 2010-10-31 18:01:20Z roland $ 3 * Copyright (C) 2007 Roland Krueger 4 * Created on 04.01.2006 5 * 6 * Author: Roland Krueger (www.rolandkrueger.info) 7 * 8 * This file is part of RoKlib. 9 * 10 * This library is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU Lesser General Public License 12 * as published by the Free Software Foundation; either version 2.1 of 13 * the License, or (at your option) any later version. 14 * 15 * This library is distributed in the hope that it will be useful, but 16 * WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 * Lesser General Public License for more details. 19 * 20 * You should have received a copy of the GNU Lesser General Public 21 * License along with this library; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 23 * USA 24 */ 25 package info.rolandkrueger.roklib.cli; 26 27 import java.io.BufferedReader; 28 import java.io.IOException; 29 import java.io.InputStream; 30 import java.io.InputStreamReader; 31 import java.io.OutputStream; 32 import java.io.PrintStream; 33 import java.util.logging.Logger; 34 35 /** 36 * This is a class that provides a shell similar to those of programs like 37 * <tt>gdb</tt> or <tt>bc</tt>. This class is running in a thread. It simply 38 * reads one line after the other from an input stream and hands it over to a 39 * given handler. This handler, which must implement the interface 40 * {@link CommandHandler}, can then process the command string. The input stream 41 * from which the user commands are read and the output stream to which the 42 * console's output is written are configurable. If these streams are not 43 * specified they default to the standard input and standard ouput. Thus, it is 44 * possible to read in commands from a Swing frame, for instance. 45 * 46 * @see CommandHandler 47 * @see ConsoleCommandObject 48 * @author Roland Krueger 49 */ 50 public class ConsoleThread extends Thread 51 { 52 private static Logger sLogger = Logger.getLogger (ConsoleThread.class.getPackage ().getName ()); 53 54 private boolean mShutdownRequested = false; 55 private CommandHandler mCommandHandler; 56 private String mGreetingMsg; 57 private Object mPrompt; 58 private BufferedReader mReader; 59 private InputStream mInputStream; 60 private PrintStream mOutput; 61 62 /** 63 * Default constructor. 64 */ 65 private ConsoleThread () 66 { 67 } 68 69 /** 70 * Constructs a new command console with configurable input and output 71 * streams. 72 * 73 * @param handler 74 * Class that gets passed the user input to process it further. 75 * @param greetingMsg 76 * A greeting message that is shown when the console starts up. 77 * @param prompt 78 * The command prompt. Can be something like '$' or '>' or a mutable 79 * object. The <tt>toString()</tt> method of the prompt-object is 80 * used to determine the string to be used as command prompt. For 81 * example, use a date object here that will return the current date 82 * and time in its <tt>toString()</tt> method. 83 * @param outStream 84 * Output stream that will be used to write the command prompt to. 85 * Note that the output of specific commands will not be written to 86 * this output stream if this is not configured by the respective 87 * command objects. See org.pi4.simplesim.util.CommandObject for 88 * further information. 89 * @param inStream 90 * Input stream that is used to read the user's input from. 91 */ 92 public ConsoleThread (CommandHandler handler, String greetingMsg, Object prompt, 93 OutputStream outStream, InputStream inStream) 94 { 95 this (); 96 mReader = new BufferedReader (new InputStreamReader (inStream)); 97 mInputStream = inStream; 98 mOutput = new PrintStream (System.out); 99 mCommandHandler = handler; 100 mPrompt = prompt; 101 mGreetingMsg = greetingMsg; 102 startThread (); 103 } 104 105 /** 106 * Constructs a new command console with <tt>stdin</tt> and <tt>stdout</tt> as 107 * the default input and output streams. 108 * 109 * @param handler 110 * Class that gets passed the user input to process it further. 111 * @param greetingMsg 112 * A greeting message that is shown when the console starts up. 113 * @param prompt 114 * The command prompt. Can be something like '$' or '>' or a mutable 115 * object. The <tt>toString()</tt> method of the prompt-object is 116 * used to determine the string to be used as command prompt. For 117 * example, use a date object here that will return the current date 118 * and time in its <tt>toString()</tt> method. 119 */ 120 public ConsoleThread (CommandHandler handler, String greetingMsg, String prompt) 121 { 122 this (handler, greetingMsg, prompt, System.out, System.in); 123 } 124 125 /** 126 * Starts the console thread. 127 */ 128 private void startThread () 129 { 130 assert mGreetingMsg != null && mPrompt != null; 131 mOutput.println (mGreetingMsg); 132 mOutput.print (mPrompt); 133 start (); 134 sLogger.info ("Console thread started."); 135 } 136 137 @Override 138 public void run () 139 { 140 while (! mShutdownRequested) 141 { 142 try 143 { 144 String line = mReader.readLine (); 145 mCommandHandler.handleCommand (line); 146 mOutput.print (mPrompt); 147 } catch (IOException ioExc) 148 { 149 // TODO: error handling 150 ioExc.printStackTrace (); 151 } 152 } 153 sLogger.info ("Shutting down console thread."); 154 } 155 156 /** 157 * Changes the console's prompt to a new prompt object. The 158 * <tt>toString()</tt> method of the prompt object is used to determine the 159 * string to be used as the command prompt. 160 * 161 * @param newPrompt 162 * the new command line prompt to be used by this console. 163 */ 164 public synchronized void setPrompt (Object newPrompt) 165 { 166 assert newPrompt != null; 167 mPrompt = newPrompt; 168 } 169 170 /** 171 * Returns the object that represents the console prompt. This may be a string 172 * with a character sequence, such as <code>">"</code>, for example. To 173 * print out the prompt on the console, the prompt object's 174 * <code>toString</code> method is used. 175 * 176 * @return the object that represents the console prompt 177 */ 178 public Object getPrompt () 179 { 180 return mPrompt; 181 } 182 183 /** 184 * Closes the console and stops the associated thread. 185 */ 186 public synchronized void shutdown () 187 { 188 sLogger.info ("Requesting shutdown of console thread."); 189 mShutdownRequested = true; 190 try 191 { 192 mReader.close (); 193 } catch (IOException ioExc) 194 { 195 // TODO: error handling 196 ioExc.printStackTrace (); 197 } 198 } 199 200 /** 201 * Returns the output stream where the console's output is written to. 202 * 203 * @return the output stream where the console's output is written to. 204 */ 205 public OutputStream getOutputStream () 206 { 207 return mOutput; 208 } 209 210 /** 211 * Returns the input stream from which the user's input is read from. 212 * 213 * @return the input stream from which the user's input is read from. 214 */ 215 public InputStream getInputStream () 216 { 217 return mInputStream; 218 } 219 220 /** 221 * Sets the output stream where the console's output is written to. 222 * 223 * @param outStream 224 * the output stream where the console's output is written to. 225 */ 226 public synchronized void setOutputStream (OutputStream outStream) 227 { 228 assert outStream != null; 229 mOutput = new PrintStream (outStream); 230 } 231 232 /** 233 * Sets the input stream from which the user's input is read from. 234 * 235 * @param inStream 236 * the input stream from which the user's input is read from. 237 */ 238 public synchronized void setInputStream (InputStream inStream) 239 { 240 assert inStream != null; 241 mReader = new BufferedReader (new InputStreamReader (inStream)); 242 mInputStream = inStream; 243 } 244 }