    001    /**
    002     *      jline - Java console input library
    003     *      Copyright (c) 2002, 2003, 2004, 2005, 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