Home » openjdk-7 » java » io » [javadoc | source]

    1   /*
    2    * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package java.io;
   27   
   28   import java.util;
   29   import java.nio.charset.Charset;
   30   import sun.nio.cs.StreamDecoder;
   31   import sun.nio.cs.StreamEncoder;
   32   
   33   /**
   34    * Methods to access the character-based console device, if any, associated
   35    * with the current Java virtual machine.
   36    *
   37    * <p> Whether a virtual machine has a console is dependent upon the
   38    * underlying platform and also upon the manner in which the virtual
   39    * machine is invoked.  If the virtual machine is started from an
   40    * interactive command line without redirecting the standard input and
   41    * output streams then its console will exist and will typically be
   42    * connected to the keyboard and display from which the virtual machine
   43    * was launched.  If the virtual machine is started automatically, for
   44    * example by a background job scheduler, then it will typically not
   45    * have a console.
   46    * <p>
   47    * If this virtual machine has a console then it is represented by a
   48    * unique instance of this class which can be obtained by invoking the
   49    * {@link java.lang.System#console()} method.  If no console device is
   50    * available then an invocation of that method will return <tt>null</tt>.
   51    * <p>
   52    * Read and write operations are synchronized to guarantee the atomic
   53    * completion of critical operations; therefore invoking methods
   54    * {@link #readLine()}, {@link #readPassword()}, {@link #format format()},
   55    * {@link #printf printf()} as well as the read, format and write operations
   56    * on the objects returned by {@link #reader()} and {@link #writer()} may
   57    * block in multithreaded scenarios.
   58    * <p>
   59    * Invoking <tt>close()</tt> on the objects returned by the {@link #reader()}
   60    * and the {@link #writer()} will not close the underlying stream of those
   61    * objects.
   62    * <p>
   63    * The console-read methods return <tt>null</tt> when the end of the
   64    * console input stream is reached, for example by typing control-D on
   65    * Unix or control-Z on Windows.  Subsequent read operations will succeed
   66    * if additional characters are later entered on the console's input
   67    * device.
   68    * <p>
   69    * Unless otherwise specified, passing a <tt>null</tt> argument to any method
   70    * in this class will cause a {@link NullPointerException} to be thrown.
   71    * <p>
   72    * <b>Security note:</b>
   73    * If an application needs to read a password or other secure data, it should
   74    * use {@link #readPassword()} or {@link #readPassword(String, Object...)} and
   75    * manually zero the returned character array after processing to minimize the
   76    * lifetime of sensitive data in memory.
   77    *
   78    * <blockquote><pre>
   79    * Console cons;
   80    * char[] passwd;
   81    * if ((cons = System.console()) != null &&
   82    *     (passwd = cons.readPassword("[%s]", "Password:")) != null) {
   83    *     ...
   84    *     java.util.Arrays.fill(passwd, ' ');
   85    * }
   86    * </pre></blockquote>
   87    *
   88    * @author  Xueming Shen
   89    * @since   1.6
   90    */
   91   
   92   public final class Console implements Flushable
   93   {
   94      /**
   95       * Retrieves the unique {@link java.io.PrintWriter PrintWriter} object
   96       * associated with this console.
   97       *
   98       * @return  The printwriter associated with this console
   99       */
  100       public PrintWriter writer() {
  101           return pw;
  102       }
  103   
  104      /**
  105       * Retrieves the unique {@link java.io.Reader Reader} object associated
  106       * with this console.
  107       * <p>
  108       * This method is intended to be used by sophisticated applications, for
  109       * example, a {@link java.util.Scanner} object which utilizes the rich
  110       * parsing/scanning functionality provided by the <tt>Scanner</tt>:
  111       * <blockquote><pre>
  112       * Console con = System.console();
  113       * if (con != null) {
  114       *     Scanner sc = new Scanner(con.reader());
  115       *     ...
  116       * }
  117       * </pre></blockquote>
  118       * <p>
  119       * For simple applications requiring only line-oriented reading, use
  120       * <tt>{@link #readLine}</tt>.
  121       * <p>
  122       * The bulk read operations {@link java.io.Reader#read(char[]) read(char[]) },
  123       * {@link java.io.Reader#read(char[], int, int) read(char[], int, int) } and
  124       * {@link java.io.Reader#read(java.nio.CharBuffer) read(java.nio.CharBuffer)}
  125       * on the returned object will not read in characters beyond the line
  126       * bound for each invocation, even if the destination buffer has space for
  127       * more characters. A line bound is considered to be any one of a line feed
  128       * (<tt>'\n'</tt>), a carriage return (<tt>'\r'</tt>), a carriage return
  129       * followed immediately by a linefeed, or an end of stream.
  130       *
  131       * @return  The reader associated with this console
  132       */
  133       public Reader reader() {
  134           return reader;
  135       }
  136   
  137      /**
  138       * Writes a formatted string to this console's output stream using
  139       * the specified format string and arguments.
  140       *
  141       * @param  fmt
  142       *         A format string as described in <a
  143       *         href="../util/Formatter.html#syntax">Format string syntax</a>
  144       *
  145       * @param  args
  146       *         Arguments referenced by the format specifiers in the format
  147       *         string.  If there are more arguments than format specifiers, the
  148       *         extra arguments are ignored.  The number of arguments is
  149       *         variable and may be zero.  The maximum number of arguments is
  150       *         limited by the maximum dimension of a Java array as defined by
  151       *         <cite>The Java&trade; Virtual Machine Specification</cite>.
  152       *         The behaviour on a
  153       *         <tt>null</tt> argument depends on the <a
  154       *         href="../util/Formatter.html#syntax">conversion</a>.
  155       *
  156       * @throws  IllegalFormatException
  157       *          If a format string contains an illegal syntax, a format
  158       *          specifier that is incompatible with the given arguments,
  159       *          insufficient arguments given the format string, or other
  160       *          illegal conditions.  For specification of all possible
  161       *          formatting errors, see the <a
  162       *          href="../util/Formatter.html#detail">Details</a> section
  163       *          of the formatter class specification.
  164       *
  165       * @return  This console
  166       */
  167       public Console format(String fmt, Object ...args) {
  168           formatter.format(fmt, args).flush();
  169           return this;
  170       }
  171   
  172      /**
  173       * A convenience method to write a formatted string to this console's
  174       * output stream using the specified format string and arguments.
  175       *
  176       * <p> An invocation of this method of the form <tt>con.printf(format,
  177       * args)</tt> behaves in exactly the same way as the invocation of
  178       * <pre>con.format(format, args)</pre>.
  179       *
  180       * @param  format
  181       *         A format string as described in <a
  182       *         href="../util/Formatter.html#syntax">Format string syntax</a>.
  183       *
  184       * @param  args
  185       *         Arguments referenced by the format specifiers in the format
  186       *         string.  If there are more arguments than format specifiers, the
  187       *         extra arguments are ignored.  The number of arguments is
  188       *         variable and may be zero.  The maximum number of arguments is
  189       *         limited by the maximum dimension of a Java array as defined by
  190       *         <cite>The Java&trade; Virtual Machine Specification</cite>.
  191       *         The behaviour on a
  192       *         <tt>null</tt> argument depends on the <a
  193       *         href="../util/Formatter.html#syntax">conversion</a>.
  194       *
  195       * @throws  IllegalFormatException
  196       *          If a format string contains an illegal syntax, a format
  197       *          specifier that is incompatible with the given arguments,
  198       *          insufficient arguments given the format string, or other
  199       *          illegal conditions.  For specification of all possible
  200       *          formatting errors, see the <a
  201       *          href="../util/Formatter.html#detail">Details</a> section of the
  202       *          formatter class specification.
  203       *
  204       * @return  This console
  205       */
  206       public Console printf(String format, Object ... args) {
  207           return format(format, args);
  208       }
  209   
  210      /**
  211       * Provides a formatted prompt, then reads a single line of text from the
  212       * console.
  213       *
  214       * @param  fmt
  215       *         A format string as described in <a
  216       *         href="../util/Formatter.html#syntax">Format string syntax</a>.
  217       *
  218       * @param  args
  219       *         Arguments referenced by the format specifiers in the format
  220       *         string.  If there are more arguments than format specifiers, the
  221       *         extra arguments are ignored.  The maximum number of arguments is
  222       *         limited by the maximum dimension of a Java array as defined by
  223       *         <cite>The Java&trade; Virtual Machine Specification</cite>.
  224       *
  225       * @throws  IllegalFormatException
  226       *          If a format string contains an illegal syntax, a format
  227       *          specifier that is incompatible with the given arguments,
  228       *          insufficient arguments given the format string, or other
  229       *          illegal conditions.  For specification of all possible
  230       *          formatting errors, see the <a
  231       *          href="../util/Formatter.html#detail">Details</a> section
  232       *          of the formatter class specification.
  233       *
  234       * @throws IOError
  235       *         If an I/O error occurs.
  236       *
  237       * @return  A string containing the line read from the console, not
  238       *          including any line-termination characters, or <tt>null</tt>
  239       *          if an end of stream has been reached.
  240       */
  241       public String readLine(String fmt, Object ... args) {
  242           String line = null;
  243           synchronized (writeLock) {
  244               synchronized(readLock) {
  245                   if (fmt.length() != 0)
  246                       pw.format(fmt, args);
  247                   try {
  248                       char[] ca = readline(false);
  249                       if (ca != null)
  250                           line = new String(ca);
  251                   } catch (IOException x) {
  252                       throw new IOError(x);
  253                   }
  254               }
  255           }
  256           return line;
  257       }
  258   
  259      /**
  260       * Reads a single line of text from the console.
  261       *
  262       * @throws IOError
  263       *         If an I/O error occurs.
  264       *
  265       * @return  A string containing the line read from the console, not
  266       *          including any line-termination characters, or <tt>null</tt>
  267       *          if an end of stream has been reached.
  268       */
  269       public String readLine() {
  270           return readLine("");
  271       }
  272   
  273      /**
  274       * Provides a formatted prompt, then reads a password or passphrase from
  275       * the console with echoing disabled.
  276       *
  277       * @param  fmt
  278       *         A format string as described in <a
  279       *         href="../util/Formatter.html#syntax">Format string syntax</a>
  280       *         for the prompt text.
  281       *
  282       * @param  args
  283       *         Arguments referenced by the format specifiers in the format
  284       *         string.  If there are more arguments than format specifiers, the
  285       *         extra arguments are ignored.  The maximum number of arguments is
  286       *         limited by the maximum dimension of a Java array as defined by
  287       *         <cite>The Java&trade; Virtual Machine Specification</cite>.
  288       *
  289       * @throws  IllegalFormatException
  290       *          If a format string contains an illegal syntax, a format
  291       *          specifier that is incompatible with the given arguments,
  292       *          insufficient arguments given the format string, or other
  293       *          illegal conditions.  For specification of all possible
  294       *          formatting errors, see the <a
  295       *          href="../util/Formatter.html#detail">Details</a>
  296       *          section of the formatter class specification.
  297       *
  298       * @throws IOError
  299       *         If an I/O error occurs.
  300       *
  301       * @return  A character array containing the password or passphrase read
  302       *          from the console, not including any line-termination characters,
  303       *          or <tt>null</tt> if an end of stream has been reached.
  304       */
  305       public char[] readPassword(String fmt, Object ... args) {
  306           char[] passwd = null;
  307           synchronized (writeLock) {
  308               synchronized(readLock) {
  309                   try {
  310                       echoOff = echo(false);
  311                   } catch (IOException x) {
  312                       throw new IOError(x);
  313                   }
  314                   IOError ioe = null;
  315                   try {
  316                       if (fmt.length() != 0)
  317                           pw.format(fmt, args);
  318                       passwd = readline(true);
  319                   } catch (IOException x) {
  320                       ioe = new IOError(x);
  321                   } finally {
  322                       try {
  323                           echoOff = echo(true);
  324                       } catch (IOException x) {
  325                           if (ioe == null)
  326                               ioe = new IOError(x);
  327                           else
  328                               ioe.addSuppressed(x);
  329                       }
  330                       if (ioe != null)
  331                           throw ioe;
  332                   }
  333                   pw.println();
  334               }
  335           }
  336           return passwd;
  337       }
  338   
  339      /**
  340       * Reads a password or passphrase from the console with echoing disabled
  341       *
  342       * @throws IOError
  343       *         If an I/O error occurs.
  344       *
  345       * @return  A character array containing the password or passphrase read
  346       *          from the console, not including any line-termination characters,
  347       *          or <tt>null</tt> if an end of stream has been reached.
  348       */
  349       public char[] readPassword() {
  350           return readPassword("");
  351       }
  352   
  353       /**
  354        * Flushes the console and forces any buffered output to be written
  355        * immediately .
  356        */
  357       public void flush() {
  358           pw.flush();
  359       }
  360   
  361       private Object readLock;
  362       private Object writeLock;
  363       private Reader reader;
  364       private Writer out;
  365       private PrintWriter pw;
  366       private Formatter formatter;
  367       private Charset cs;
  368       private char[] rcb;
  369       private static native String encoding();
  370       private static native boolean echo(boolean on) throws IOException;
  371       private static boolean echoOff;
  372   
  373       private char[] readline(boolean zeroOut) throws IOException {
  374           int len = reader.read(rcb, 0, rcb.length);
  375           if (len < 0)
  376               return null;  //EOL
  377           if (rcb[len-1] == '\r')
  378               len--;        //remove CR at end;
  379           else if (rcb[len-1] == '\n') {
  380               len--;        //remove LF at end;
  381               if (len > 0 && rcb[len-1] == '\r')
  382                   len--;    //remove the CR, if there is one
  383           }
  384           char[] b = new char[len];
  385           if (len > 0) {
  386               System.arraycopy(rcb, 0, b, 0, len);
  387               if (zeroOut) {
  388                   Arrays.fill(rcb, 0, len, ' ');
  389               }
  390           }
  391           return b;
  392       }
  393   
  394       private char[] grow() {
  395           assert Thread.holdsLock(readLock);
  396           char[] t = new char[rcb.length * 2];
  397           System.arraycopy(rcb, 0, t, 0, rcb.length);
  398           rcb = t;
  399           return rcb;
  400       }
  401   
  402       class LineReader extends Reader {
  403           private Reader in;
  404           private char[] cb;
  405           private int nChars, nextChar;
  406           boolean leftoverLF;
  407           LineReader(Reader in) {
  408               this.in = in;
  409               cb = new char[1024];
  410               nextChar = nChars = 0;
  411               leftoverLF = false;
  412           }
  413           public void close () {}
  414           public boolean ready() throws IOException {
  415               //in.ready synchronizes on readLock already
  416               return in.ready();
  417           }
  418   
  419           public int read(char cbuf[], int offset, int length)
  420               throws IOException
  421           {
  422               int off = offset;
  423               int end = offset + length;
  424               if (offset < 0 || offset > cbuf.length || length < 0 ||
  425                   end < 0 || end > cbuf.length) {
  426                   throw new IndexOutOfBoundsException();
  427               }
  428               synchronized(readLock) {
  429                   boolean eof = false;
  430                   char c = 0;
  431                   for (;;) {
  432                       if (nextChar >= nChars) {   //fill
  433                           int n = 0;
  434                           do {
  435                               n = in.read(cb, 0, cb.length);
  436                           } while (n == 0);
  437                           if (n > 0) {
  438                               nChars = n;
  439                               nextChar = 0;
  440                               if (n < cb.length &&
  441                                   cb[n-1] != '\n' && cb[n-1] != '\r') {
  442                                   /*
  443                                    * we're in canonical mode so each "fill" should
  444                                    * come back with an eol. if there no lf or nl at
  445                                    * the end of returned bytes we reached an eof.
  446                                    */
  447                                   eof = true;
  448                               }
  449                           } else { /*EOF*/
  450                               if (off - offset == 0)
  451                                   return -1;
  452                               return off - offset;
  453                           }
  454                       }
  455                       if (leftoverLF && cbuf == rcb && cb[nextChar] == '\n') {
  456                           /*
  457                            * if invoked by our readline, skip the leftover, otherwise
  458                            * return the LF.
  459                            */
  460                           nextChar++;
  461                       }
  462                       leftoverLF = false;
  463                       while (nextChar < nChars) {
  464                           c = cbuf[off++] = cb[nextChar];
  465                           cb[nextChar++] = 0;
  466                           if (c == '\n') {
  467                               return off - offset;
  468                           } else if (c == '\r') {
  469                               if (off == end) {
  470                                   /* no space left even the next is LF, so return
  471                                    * whatever we have if the invoker is not our
  472                                    * readLine()
  473                                    */
  474                                   if (cbuf == rcb) {
  475                                       cbuf = grow();
  476                                       end = cbuf.length;
  477                                   } else {
  478                                       leftoverLF = true;
  479                                       return off - offset;
  480                                   }
  481                               }
  482                               if (nextChar == nChars && in.ready()) {
  483                                   /*
  484                                    * we have a CR and we reached the end of
  485                                    * the read in buffer, fill to make sure we
  486                                    * don't miss a LF, if there is one, it's possible
  487                                    * that it got cut off during last round reading
  488                                    * simply because the read in buffer was full.
  489                                    */
  490                                   nChars = in.read(cb, 0, cb.length);
  491                                   nextChar = 0;
  492                               }
  493                               if (nextChar < nChars && cb[nextChar] == '\n') {
  494                                   cbuf[off++] = '\n';
  495                                   nextChar++;
  496                               }
  497                               return off - offset;
  498                           } else if (off == end) {
  499                              if (cbuf == rcb) {
  500                                   cbuf = grow();
  501                                   end = cbuf.length;
  502                              } else {
  503                                  return off - offset;
  504                              }
  505                           }
  506                       }
  507                       if (eof)
  508                           return off - offset;
  509                   }
  510               }
  511           }
  512       }
  513   
  514       // Set up JavaIOAccess in SharedSecrets
  515       static {
  516           try {
  517               // Add a shutdown hook to restore console's echo state should
  518               // it be necessary.
  519               sun.misc.SharedSecrets.getJavaLangAccess()
  520                   .registerShutdownHook(0 /* shutdown hook invocation order */,
  521                       false /* only register if shutdown is not in progress */,
  522                       new Runnable() {
  523                           public void run() {
  524                               try {
  525                                   if (echoOff) {
  526                                       echo(true);
  527                                   }
  528                               } catch (IOException x) { }
  529                           }
  530                       });
  531           } catch (IllegalStateException e) {
  532               // shutdown is already in progress and console is first used
  533               // by a shutdown hook
  534           }
  535   
  536           sun.misc.SharedSecrets.setJavaIOAccess(new sun.misc.JavaIOAccess() {
  537               public Console console() {
  538                   if (istty()) {
  539                       if (cons == null)
  540                           cons = new Console();
  541                       return cons;
  542                   }
  543                   return null;
  544               }
  545   
  546               public Charset charset() {
  547                   // This method is called in sun.security.util.Password,
  548                   // cons already exists when this method is called
  549                   return cons.cs;
  550               }
  551           });
  552       }
  553       private static Console cons;
  554       private native static boolean istty();
  555       private Console() {
  556           readLock = new Object();
  557           writeLock = new Object();
  558           String csname = encoding();
  559           if (csname != null) {
  560               try {
  561                   cs = Charset.forName(csname);
  562               } catch (Exception x) {}
  563           }
  564           if (cs == null)
  565               cs = Charset.defaultCharset();
  566           out = StreamEncoder.forOutputStreamWriter(
  567                     new FileOutputStream(FileDescriptor.out),
  568                     writeLock,
  569                     cs);
  570           pw = new PrintWriter(out, true) { public void close() {} };
  571           formatter = new Formatter(out);
  572           reader = new LineReader(StreamDecoder.forInputStreamReader(
  573                        new FileInputStream(FileDescriptor.in),
  574                        readLock,
  575                        cs));
  576           rcb = new char[1024];
  577       }
  578   }

Home » openjdk-7 » java » io » [javadoc | source]