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