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    import java.util.*;
040    
041    
042    /**
043     *      An {@link InputStream} implementation that wraps a {@link ConsoleReader}.
044     *      It is useful for setting up the {@link System#in} for a generic
045     *      console.
046     *
047     *  @author  <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
048     */
049    public class ConsoleReaderInputStream
050            extends SequenceInputStream
051    {
052            private static InputStream systemIn = System.in;
053    
054    
055            public static void setIn ()
056                    throws IOException
057            {
058                    setIn (new ConsoleReader ());
059            }
060    
061    
062            public static void setIn (final ConsoleReader reader)
063            {
064                    System.setIn (new ConsoleReaderInputStream (reader));
065            }
066    
067    
068            /**
069             *  Restore the original {@link System#in} input stream.
070             */
071            public static void restoreIn ()
072            {
073                    System.setIn (systemIn);
074            }
075    
076    
077            public ConsoleReaderInputStream (final ConsoleReader reader)
078            {
079                    super (new ConsoleEnumeration (reader));
080            }
081    
082    
083            private static class ConsoleEnumeration
084                    implements Enumeration
085            {
086                    private final ConsoleReader reader;
087                    private ConsoleLineInputStream next = null;
088                    private ConsoleLineInputStream prev = null;
089    
090    
091                    public ConsoleEnumeration (final ConsoleReader reader)
092                    {
093                            this.reader = reader;
094                    }
095    
096    
097                    public Object nextElement ()
098                    {
099                            if (next != null)
100                            {
101                                    InputStream n = next;
102                                    prev = next;
103                                    next = null;
104                                    return n;
105                            }
106    
107                            return new ConsoleLineInputStream (reader);
108                    }
109    
110    
111                    public boolean hasMoreElements ()
112                    {
113                            // the last line was null
114                            if (prev != null && prev.wasNull == true)
115                                    return false;
116    
117                            if (next == null)
118                                    next = (ConsoleLineInputStream)nextElement ();
119    
120                            return next != null;
121                    }
122            }       
123    
124    
125            private static class ConsoleLineInputStream
126                    extends InputStream
127            {
128                    private final ConsoleReader reader;
129                    private String line = null;
130                    private int index = 0;
131                    private boolean eol = false;
132                    protected boolean wasNull = false;
133    
134                    public ConsoleLineInputStream (final ConsoleReader reader)
135                    {
136                            this.reader = reader;
137                    }
138    
139    
140                    public int read ()
141                            throws IOException
142                    {
143                            if (eol)
144                                    return -1;
145    
146                            if (line == null)
147                                    line = reader.readLine ();
148    
149                            if (line == null)
150                            {
151                                    wasNull = true;
152                                    return -1;
153                            }
154    
155                            if (index >= line.length ())
156                            {
157                                    eol = true;
158                                    return '\n'; // lines are ended with a newline
159                            }
160    
161                            return line.charAt (index++);
162                    }
163            }
164    }
165