rt/emul/compact/src/main/java/java/io/FileInputStream.java
author Jaroslav Tulach <jtulach@netbeans.org>
Thu, 03 Oct 2013 15:40:35 +0200
branchjdk7-b147
changeset 1334 588d5bf7a560
child 1337 c794024954b5
permissions -rw-r--r--
Set of JDK classes needed to run javac
     1 /*
     2  * Copyright (c) 1994, 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.nio.channels.FileChannel;
    29 import sun.nio.ch.FileChannelImpl;
    30 
    31 
    32 /**
    33  * A <code>FileInputStream</code> obtains input bytes
    34  * from a file in a file system. What files
    35  * are  available depends on the host environment.
    36  *
    37  * <p><code>FileInputStream</code> is meant for reading streams of raw bytes
    38  * such as image data. For reading streams of characters, consider using
    39  * <code>FileReader</code>.
    40  *
    41  * @author  Arthur van Hoff
    42  * @see     java.io.File
    43  * @see     java.io.FileDescriptor
    44  * @see     java.io.FileOutputStream
    45  * @see     java.nio.file.Files#newInputStream
    46  * @since   JDK1.0
    47  */
    48 public
    49 class FileInputStream extends InputStream
    50 {
    51     /* File Descriptor - handle to the open file */
    52     private final FileDescriptor fd;
    53 
    54     private FileChannel channel = null;
    55 
    56     private final Object closeLock = new Object();
    57     private volatile boolean closed = false;
    58 
    59     private static final ThreadLocal<Boolean> runningFinalize =
    60         new ThreadLocal<>();
    61 
    62     private static boolean isRunningFinalize() {
    63         Boolean val;
    64         if ((val = runningFinalize.get()) != null)
    65             return val.booleanValue();
    66         return false;
    67     }
    68 
    69     /**
    70      * Creates a <code>FileInputStream</code> by
    71      * opening a connection to an actual file,
    72      * the file named by the path name <code>name</code>
    73      * in the file system.  A new <code>FileDescriptor</code>
    74      * object is created to represent this file
    75      * connection.
    76      * <p>
    77      * First, if there is a security
    78      * manager, its <code>checkRead</code> method
    79      * is called with the <code>name</code> argument
    80      * as its argument.
    81      * <p>
    82      * If the named file does not exist, is a directory rather than a regular
    83      * file, or for some other reason cannot be opened for reading then a
    84      * <code>FileNotFoundException</code> is thrown.
    85      *
    86      * @param      name   the system-dependent file name.
    87      * @exception  FileNotFoundException  if the file does not exist,
    88      *                   is a directory rather than a regular file,
    89      *                   or for some other reason cannot be opened for
    90      *                   reading.
    91      * @exception  SecurityException      if a security manager exists and its
    92      *               <code>checkRead</code> method denies read access
    93      *               to the file.
    94      * @see        java.lang.SecurityManager#checkRead(java.lang.String)
    95      */
    96     public FileInputStream(String name) throws FileNotFoundException {
    97         this(name != null ? new File(name) : null);
    98     }
    99 
   100     /**
   101      * Creates a <code>FileInputStream</code> by
   102      * opening a connection to an actual file,
   103      * the file named by the <code>File</code>
   104      * object <code>file</code> in the file system.
   105      * A new <code>FileDescriptor</code> object
   106      * is created to represent this file connection.
   107      * <p>
   108      * First, if there is a security manager,
   109      * its <code>checkRead</code> method  is called
   110      * with the path represented by the <code>file</code>
   111      * argument as its argument.
   112      * <p>
   113      * If the named file does not exist, is a directory rather than a regular
   114      * file, or for some other reason cannot be opened for reading then a
   115      * <code>FileNotFoundException</code> is thrown.
   116      *
   117      * @param      file   the file to be opened for reading.
   118      * @exception  FileNotFoundException  if the file does not exist,
   119      *                   is a directory rather than a regular file,
   120      *                   or for some other reason cannot be opened for
   121      *                   reading.
   122      * @exception  SecurityException      if a security manager exists and its
   123      *               <code>checkRead</code> method denies read access to the file.
   124      * @see        java.io.File#getPath()
   125      * @see        java.lang.SecurityManager#checkRead(java.lang.String)
   126      */
   127     public FileInputStream(File file) throws FileNotFoundException {
   128         String name = (file != null ? file.getPath() : null);
   129         SecurityManager security = System.getSecurityManager();
   130         if (security != null) {
   131             security.checkRead(name);
   132         }
   133         if (name == null) {
   134             throw new NullPointerException();
   135         }
   136         fd = new FileDescriptor();
   137         fd.incrementAndGetUseCount();
   138         open(name);
   139     }
   140 
   141     /**
   142      * Creates a <code>FileInputStream</code> by using the file descriptor
   143      * <code>fdObj</code>, which represents an existing connection to an
   144      * actual file in the file system.
   145      * <p>
   146      * If there is a security manager, its <code>checkRead</code> method is
   147      * called with the file descriptor <code>fdObj</code> as its argument to
   148      * see if it's ok to read the file descriptor. If read access is denied
   149      * to the file descriptor a <code>SecurityException</code> is thrown.
   150      * <p>
   151      * If <code>fdObj</code> is null then a <code>NullPointerException</code>
   152      * is thrown.
   153      * <p>
   154      * This constructor does not throw an exception if <code>fdObj</code>
   155      * is {@link java.io.FileDescriptor#valid() invalid}.
   156      * However, if the methods are invoked on the resulting stream to attempt
   157      * I/O on the stream, an <code>IOException</code> is thrown.
   158      *
   159      * @param      fdObj   the file descriptor to be opened for reading.
   160      * @throws     SecurityException      if a security manager exists and its
   161      *                 <code>checkRead</code> method denies read access to the
   162      *                 file descriptor.
   163      * @see        SecurityManager#checkRead(java.io.FileDescriptor)
   164      */
   165     public FileInputStream(FileDescriptor fdObj) {
   166         SecurityManager security = System.getSecurityManager();
   167         if (fdObj == null) {
   168             throw new NullPointerException();
   169         }
   170         if (security != null) {
   171             security.checkRead(fdObj);
   172         }
   173         fd = fdObj;
   174 
   175         /*
   176          * FileDescriptor is being shared by streams.
   177          * Ensure that it's GC'ed only when all the streams/channels are done
   178          * using it.
   179          */
   180         fd.incrementAndGetUseCount();
   181     }
   182 
   183     /**
   184      * Opens the specified file for reading.
   185      * @param name the name of the file
   186      */
   187     private native void open(String name) throws FileNotFoundException;
   188 
   189     /**
   190      * Reads a byte of data from this input stream. This method blocks
   191      * if no input is yet available.
   192      *
   193      * @return     the next byte of data, or <code>-1</code> if the end of the
   194      *             file is reached.
   195      * @exception  IOException  if an I/O error occurs.
   196      */
   197     public native int read() throws IOException;
   198 
   199     /**
   200      * Reads a subarray as a sequence of bytes.
   201      * @param b the data to be written
   202      * @param off the start offset in the data
   203      * @param len the number of bytes that are written
   204      * @exception IOException If an I/O error has occurred.
   205      */
   206     private native int readBytes(byte b[], int off, int len) throws IOException;
   207 
   208     /**
   209      * Reads up to <code>b.length</code> bytes of data from this input
   210      * stream into an array of bytes. This method blocks until some input
   211      * is available.
   212      *
   213      * @param      b   the buffer into which the data is read.
   214      * @return     the total number of bytes read into the buffer, or
   215      *             <code>-1</code> if there is no more data because the end of
   216      *             the file has been reached.
   217      * @exception  IOException  if an I/O error occurs.
   218      */
   219     public int read(byte b[]) throws IOException {
   220         return readBytes(b, 0, b.length);
   221     }
   222 
   223     /**
   224      * Reads up to <code>len</code> bytes of data from this input stream
   225      * into an array of bytes. If <code>len</code> is not zero, the method
   226      * blocks until some input is available; otherwise, no
   227      * bytes are read and <code>0</code> is returned.
   228      *
   229      * @param      b     the buffer into which the data is read.
   230      * @param      off   the start offset in the destination array <code>b</code>
   231      * @param      len   the maximum number of bytes read.
   232      * @return     the total number of bytes read into the buffer, or
   233      *             <code>-1</code> if there is no more data because the end of
   234      *             the file has been reached.
   235      * @exception  NullPointerException If <code>b</code> is <code>null</code>.
   236      * @exception  IndexOutOfBoundsException If <code>off</code> is negative,
   237      * <code>len</code> is negative, or <code>len</code> is greater than
   238      * <code>b.length - off</code>
   239      * @exception  IOException  if an I/O error occurs.
   240      */
   241     public int read(byte b[], int off, int len) throws IOException {
   242         return readBytes(b, off, len);
   243     }
   244 
   245     /**
   246      * Skips over and discards <code>n</code> bytes of data from the
   247      * input stream.
   248      *
   249      * <p>The <code>skip</code> method may, for a variety of
   250      * reasons, end up skipping over some smaller number of bytes,
   251      * possibly <code>0</code>. If <code>n</code> is negative, an
   252      * <code>IOException</code> is thrown, even though the <code>skip</code>
   253      * method of the {@link InputStream} superclass does nothing in this case.
   254      * The actual number of bytes skipped is returned.
   255      *
   256      * <p>This method may skip more bytes than are remaining in the backing
   257      * file. This produces no exception and the number of bytes skipped
   258      * may include some number of bytes that were beyond the EOF of the
   259      * backing file. Attempting to read from the stream after skipping past
   260      * the end will result in -1 indicating the end of the file.
   261      *
   262      * @param      n   the number of bytes to be skipped.
   263      * @return     the actual number of bytes skipped.
   264      * @exception  IOException  if n is negative, if the stream does not
   265      *             support seek, or if an I/O error occurs.
   266      */
   267     public native long skip(long n) throws IOException;
   268 
   269     /**
   270      * Returns an estimate of the number of remaining bytes that can be read (or
   271      * skipped over) from this input stream without blocking by the next
   272      * invocation of a method for this input stream. The next invocation might be
   273      * the same thread or another thread.  A single read or skip of this
   274      * many bytes will not block, but may read or skip fewer bytes.
   275      *
   276      * <p> In some cases, a non-blocking read (or skip) may appear to be
   277      * blocked when it is merely slow, for example when reading large
   278      * files over slow networks.
   279      *
   280      * @return     an estimate of the number of remaining bytes that can be read
   281      *             (or skipped over) from this input stream without blocking.
   282      * @exception  IOException  if this file input stream has been closed by calling
   283      *             {@code close} or an I/O error occurs.
   284      */
   285     public native int available() throws IOException;
   286 
   287     /**
   288      * Closes this file input stream and releases any system resources
   289      * associated with the stream.
   290      *
   291      * <p> If this stream has an associated channel then the channel is closed
   292      * as well.
   293      *
   294      * @exception  IOException  if an I/O error occurs.
   295      *
   296      * @revised 1.4
   297      * @spec JSR-51
   298      */
   299     public void close() throws IOException {
   300         synchronized (closeLock) {
   301             if (closed) {
   302                 return;
   303             }
   304             closed = true;
   305         }
   306         if (channel != null) {
   307             /*
   308              * Decrement the FD use count associated with the channel
   309              * The use count is incremented whenever a new channel
   310              * is obtained from this stream.
   311              */
   312            fd.decrementAndGetUseCount();
   313            channel.close();
   314         }
   315 
   316         /*
   317          * Decrement the FD use count associated with this stream
   318          */
   319         int useCount = fd.decrementAndGetUseCount();
   320 
   321         /*
   322          * If FileDescriptor is still in use by another stream, the finalizer
   323          * will not close it.
   324          */
   325         if ((useCount <= 0) || !isRunningFinalize()) {
   326             close0();
   327         }
   328     }
   329 
   330     /**
   331      * Returns the <code>FileDescriptor</code>
   332      * object  that represents the connection to
   333      * the actual file in the file system being
   334      * used by this <code>FileInputStream</code>.
   335      *
   336      * @return     the file descriptor object associated with this stream.
   337      * @exception  IOException  if an I/O error occurs.
   338      * @see        java.io.FileDescriptor
   339      */
   340     public final FileDescriptor getFD() throws IOException {
   341         if (fd != null) return fd;
   342         throw new IOException();
   343     }
   344 
   345     /**
   346      * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
   347      * object associated with this file input stream.
   348      *
   349      * <p> The initial {@link java.nio.channels.FileChannel#position()
   350      * </code>position<code>} of the returned channel will be equal to the
   351      * number of bytes read from the file so far.  Reading bytes from this
   352      * stream will increment the channel's position.  Changing the channel's
   353      * position, either explicitly or by reading, will change this stream's
   354      * file position.
   355      *
   356      * @return  the file channel associated with this file input stream
   357      *
   358      * @since 1.4
   359      * @spec JSR-51
   360      */
   361     public FileChannel getChannel() {
   362         synchronized (this) {
   363             if (channel == null) {
   364                 channel = FileChannelImpl.open(fd, true, false, this);
   365 
   366                 /*
   367                  * Increment fd's use count. Invoking the channel's close()
   368                  * method will result in decrementing the use count set for
   369                  * the channel.
   370                  */
   371                 fd.incrementAndGetUseCount();
   372             }
   373             return channel;
   374         }
   375     }
   376 
   377     private static native void initIDs();
   378 
   379     private native void close0() throws IOException;
   380 
   381     static {
   382         initIDs();
   383     }
   384 
   385     /**
   386      * Ensures that the <code>close</code> method of this file input stream is
   387      * called when there are no more references to it.
   388      *
   389      * @exception  IOException  if an I/O error occurs.
   390      * @see        java.io.FileInputStream#close()
   391      */
   392     protected void finalize() throws IOException {
   393         if ((fd != null) &&  (fd != FileDescriptor.in)) {
   394 
   395             /*
   396              * Finalizer should not release the FileDescriptor if another
   397              * stream is still using it. If the user directly invokes
   398              * close() then the FileDescriptor is also released.
   399              */
   400             runningFinalize.set(Boolean.TRUE);
   401             try {
   402                 close();
   403             } finally {
   404                 runningFinalize.set(Boolean.FALSE);
   405             }
   406         }
   407     }
   408 }