001    /**
002     *      jline - Java console input library
003     *      Copyright (c) 2002,2003 Marc Prud'hommeaux mwp1@cornell.edu
004     *      
005     *      This library is free software; you can redistribute it and/or
006     *      modify it under the terms of the GNU Lesser General Public
007     *      License as published by the Free Software Foundation; either
008     *      version 2.1 of the License, or (at your option) any later version.
009     *      
010     *      This library is distributed in the hope that it will be useful,
011     *      but WITHOUT ANY WARRANTY; without even the implied warranty of
012     *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013     *      Lesser General Public License for more details.
014     *      
015     *      You should have received a copy of the GNU Lesser General Public
016     *      License along with this library; if not, write to the Free Software
017     *      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
018     */
019    package jline;
020    
021    import java.io.*;
022    import java.util.*;
023    
024    
025    /**
026     *      An {@link InputStream} implementation that wraps a {@link ConsoleReader}.
027     *      It is useful for setting up the {@link System#in} for a generic
028     *      console.
029     *
030     *  @author  <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
031     */
032    public class ConsoleReaderInputStream
033            extends SequenceInputStream
034    {
035            private static InputStream systemIn = System.in;
036    
037    
038            public static void setIn ()
039                    throws IOException
040            {
041                    setIn (new ConsoleReader ());
042            }
043    
044    
045            public static void setIn (final ConsoleReader reader)
046            {
047                    System.setIn (new ConsoleReaderInputStream (reader));
048            }
049    
050    
051            /**
052             *  Restore the original {@link System#in} input stream.
053             */
054            public static void restoreIn ()
055            {
056                    System.setIn (systemIn);
057            }
058    
059    
060            public ConsoleReaderInputStream (final ConsoleReader reader)
061            {
062                    super (new ConsoleEnumeration (reader));
063            }
064    
065    
066            private static class ConsoleEnumeration
067                    implements Enumeration
068            {
069                    private final ConsoleReader reader;
070                    private ConsoleLineInputStream next = null;
071                    private ConsoleLineInputStream prev = null;
072    
073    
074                    public ConsoleEnumeration (final ConsoleReader reader)
075                    {
076                            this.reader = reader;
077                    }
078    
079    
080                    public Object nextElement ()
081                    {
082                            if (next != null)
083                            {
084                                    InputStream n = next;
085                                    prev = next;
086                                    next = null;
087                                    return n;
088                            }
089    
090                            return new ConsoleLineInputStream (reader);
091                    }
092    
093    
094                    public boolean hasMoreElements ()
095                    {
096                            // the last line was null
097                            if (prev != null && prev.wasNull == true)
098                                    return false;
099    
100                            if (next == null)
101                                    next = (ConsoleLineInputStream)nextElement ();
102    
103                            return next != null;
104                    }
105            }       
106    
107    
108            private static class ConsoleLineInputStream
109                    extends InputStream
110            {
111                    private final ConsoleReader reader;
112                    private String line = null;
113                    private int index = 0;
114                    private boolean eol = false;
115                    protected boolean wasNull = false;
116    
117                    public ConsoleLineInputStream (final ConsoleReader reader)
118                    {
119                            this.reader = reader;
120                    }
121    
122    
123                    public int read ()
124                            throws IOException
125                    {
126                            if (eol)
127                                    return -1;
128    
129                            if (line == null)
130                                    line = reader.readLine ();
131    
132                            if (line == null)
133                            {
134                                    wasNull = true;
135                                    return -1;
136                            }
137    
138                            if (index >= line.length ())
139                            {
140                                    eol = true;
141                                    return '\n'; // lines are ended with a newline
142                            }
143    
144                            return line.charAt (index++);
145                    }
146            }
147    }
148