View Javadoc

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>"&gt;"</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 }