001    /**
002     *      jline - Java console input library
003     *      Copyright (c) 2002-2006, Marc Prud'hommeaux <mwp1@cornell.edu>
004     *      All rights reserved.
005     *
006     *      Redistribution and use in source and binary forms, with or
007     *      without modification, are permitted provided that the following
008     *      conditions are met:
009     *
010     *      Redistributions of source code must retain the above copyright
011     *      notice, this list of conditions and the following disclaimer.
012     *
013     *      Redistributions in binary form must reproduce the above copyright
014     *      notice, this list of conditions and the following disclaimer
015     *      in the documentation and/or other materials provided with
016     *      the distribution.
017     *
018     *      Neither the name of JLine nor the names of its contributors
019     *      may be used to endorse or promote products derived from this
020     *      software without specific prior written permission.
021     *
022     *      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
023     *      "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
024     *      BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
025     *      AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
026     *      EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
027     *      FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
028     *      OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
029     *      PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
030     *      DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
031     *      AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
032     *      LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
033     *      IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
034     *      OF THE POSSIBILITY OF SUCH DAMAGE.
035     */
036    package jline;
037    
038    import java.io.*;
039    
040    /**
041     *  Representation of the input terminal for a platform. Handles
042     *      any initialization that the platform may need to perform
043     *      in order to allow the {@link ConsoleReader} to correctly handle
044     *      input.
045     *
046     *  @author  <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
047     */
048    public abstract class Terminal
049            implements ConsoleOperations
050    {
051            private static Terminal term;
052    
053    
054            /**
055             *  @see #setupTerminal
056             */
057            public static Terminal getTerminal ()
058            {
059                    return setupTerminal ();
060            }
061    
062    
063            /**
064             *  <p>Configure and return the {@link Terminal} instance for the
065             *  current platform. This will initialize any system settings
066             *  that are required for the console to be able to handle
067             *  input correctly, such as setting tabtop, buffered input, and
068             *  character echo.</p>
069             *
070             *  <p>This class will use the Terminal implementation specified in the
071             *  <em>jline.terminal</em> system property, or, if it is unset, by
072             *  detecting the operating system from the <em>os.name</em>
073             *  system property and instantiateing either the
074             *  {@link WindowsTerminal} or {@link UnixTerminal}.
075             *
076             *  @see #initializeTerminal
077             */
078            public static synchronized Terminal setupTerminal ()
079            {
080                    if (term != null)
081                            return term;
082    
083                    final Terminal t;
084    
085                    String os = System.getProperty ("os.name").toLowerCase ();
086                    String termProp = System.getProperty ("jline.terminal");
087                    if (termProp != null && termProp.length () > 0)
088                    {
089                            try
090                            {
091                                    t = (Terminal)Class.forName (termProp).newInstance ();
092                            }
093                            catch (Exception e)
094                            {
095                                    throw (IllegalArgumentException)new IllegalArgumentException (
096                                            e.toString ()).fillInStackTrace ();
097                            }
098                    }
099                    else if (os.indexOf ("windows") != -1)
100                    {
101                            t = new WindowsTerminal ();
102                    }
103                    else
104                    {
105                            t = new UnixTerminal ();
106                    }
107    
108                    try
109                    {
110                            t.initializeTerminal ();
111                    }
112                    catch (Exception e)
113                    {
114                            e.printStackTrace ();
115                            return term = new UnsupportedTerminal ();
116                    }
117    
118                    return term = t;
119            }
120    
121    
122            /** 
123             *  Returns true if the current console supports ANSI
124             *  codes.
125             */
126            public boolean isANSISupported ()
127            {
128                    return true;
129            }       
130    
131    
132            /**
133             *  Read a single character from the input stream. This might
134             *  enable a terminal implementation to better handle nuances of
135             *  the console.
136             */
137            public int readCharacter (final InputStream in)
138                    throws IOException
139            {
140                    return in.read ();
141            }
142    
143    
144            /** 
145             *  Reads a virtual key from the console. Typically, this will
146             *  just be the raw character that was entered, but in some cases,
147             *  multiple input keys will need to be translated into a single
148             *  virtual key.
149             *  
150             *  @param  in  the InputStream to read from
151             *  @return  the virtual key (e.g., {@link ConsoleOperations#VK_UP})
152             */
153            public int readVirtualKey (InputStream in)
154                    throws IOException
155            {
156                    return readCharacter (in);
157            }
158    
159    
160            /**
161             *  Initialize any system settings
162             *  that are required for the console to be able to handle
163             *  input correctly, such as setting tabtop, buffered input, and
164             *  character echo.
165             */
166            public abstract void initializeTerminal ()
167                    throws Exception;
168    
169    
170            /**
171             *  Returns the current width of the terminal (in characters)
172             */
173            public abstract int getTerminalWidth ();
174    
175    
176            /**
177             *  Returns the current height of the terminal (in lines)
178             */
179            public abstract int getTerminalHeight ();
180    
181    
182            /**
183             *  Returns true if this terminal is capable of initializing the
184             *  terminal to use jline.
185             */
186            public abstract boolean isSupported ();
187    
188    
189            /**
190             *  Returns true if the terminal will echo all characters type.
191             */
192            public abstract boolean getEcho ();
193    }