/* FileInputStream.java -- An input stream that reads from disk files.
   Copyright (C) 1998, 2002, 2003, 2004, 2005  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
 
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.io;

import gnu.java.nio.FileChannelImpl;

import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3
 * "The Java Language Specification", ISBN 0-201-63451-1
 * plus online API docs for JDK 1.2 beta from http://www.javasoft.com.
 * Status:  Believed complete and correct.
 */
 
/**
 * This class is a stream that reads its bytes from a file. 
 *
 * @author Aaron M. Renn (arenn@urbanophile.com)
 * @author Warren Levy (warrenl@cygnus.com)
 */
public class FileInputStream extends InputStream
{
  /**
   * This is the native file handle for the file this stream is reading from
   */
  private FileDescriptor fd;

  private FileChannelImpl ch;

  /**
   * This method initializes a <code>FileInputStream</code> to read from the
   * specified named file.  A security check is first made to determine
   * whether or not access to this file is allowed.  This is done by
   * calling the <code>checkRead()</code> method of the 
   * <code>SecurityManager</code>
   * (if one exists) with the name of this file.  An exception is thrown
   * if reading is not allowed.  If the file does not exist, an exception
   * is also thrown.
   *
   * @param name The name of the file this stream should read from
   *
   * @exception SecurityException If read access to the file is not allowed
   * @exception FileNotFoundException If the file does not exist 
   * or if it is a directory
   */
  public FileInputStream(String name) throws FileNotFoundException
  {
    this(new File(name));
  }

  /**
   * This method initializes a <code>FileInputStream</code> to read from the
   * specified <code>File</code> object.  A security check is first
   * made to determine
   * whether or not access to this file is allowed.  This is done by
   * calling the <code>checkRead()</code> method of the
   * <code>SecurityManager</code>
   * (if one exists) with the name of this file.  An exception is thrown
   * if reading is not allowed.  If the file does not exist, an exception
   * is also thrown.
   *
   * @param file The <code>File</code> object this stream should read from
   *
   * @exception SecurityException If read access to the file is not allowed
   * @exception FileNotFoundException If the file does not exist
   * or if it is a directory.
   */
  public FileInputStream(File file) throws FileNotFoundException
  {
    SecurityManager s = System.getSecurityManager();
    if (s != null)
      s.checkRead(file.getPath());

    try
      {
        ch = FileChannelImpl.create(file, FileChannelImpl.READ);
      }
    catch (FileNotFoundException fnfe)
      {
        throw fnfe;
      }
    catch (IOException ioe)
      {
        FileNotFoundException fnfe = new FileNotFoundException(file.getPath());
        fnfe.initCause(ioe);
        throw fnfe;
      }
  }

  /**
   * This method initializes a <code>FileInputStream</code> to read from the
   * specified <code>FileDescriptor</code> object.  A security
   * check is first made to
   * determine whether or not access to this file is allowed.  This is done by
   * calling the <code>checkRead()</code> method of the 
   * <code>SecurityManager</code>
   * (if one exists) with the specified <code>FileDescriptor</code>  
   * An exception is 
   * thrown if reading is not allowed.
   *
   * @param fdObj The <code>FileDescriptor</code> object this stream 
   * should read from
   *
   * @exception SecurityException If read access to the file is not allowed
   */
  public FileInputStream(FileDescriptor fdObj)
  {
    SecurityManager s = System.getSecurityManager();
    if (s != null)
      s.checkRead(fdObj);

    fd = fdObj;
    ch = (FileChannelImpl) fdObj.channel;
  }

  FileInputStream(FileChannelImpl ch)
  {
    this.ch = ch;
  }

  /**
   * This method returns the number of bytes that can be read from this
   * stream before a read can block.  A return of 0 indicates that blocking
   * might (or might not) occur on the very next read attempt.
   * <p>
   * This method returns the number of unread bytes remaining in the file if
   * the descriptor being read from is an actual file.  If this method is
   * reading from a ''special'' file such a the standard input, this method
   * will return the appropriate value for the stream being read.
   * <p>
   * Be aware that reads on plain files that do not reside locally might
   * possibly block even if this method says they should not.  For example,
   * a remote server might crash, preventing an NFS mounted file from being
   * read.
   *
   * @return The number of bytes that can be read before blocking could occur
   *
   * @exception IOException If an error occurs
   */
  public int available() throws IOException
  {
    return ch.available();
  }

  /**
   * This method closes the stream.  Any futher attempts to read from the
   * stream will likely generate an IOException since the underlying file
   * will be closed.
   *
   * @exception IOException If an error occurs.
   */
  public void close() throws IOException
  {
    ch.close();
  }

  protected void finalize() throws IOException
  {
    // We don't actually need this, but we include it because it is
    // mentioned in the JCL.
  }

  /**
   * This method returns a <code>FileDescriptor</code> object representing the
   * underlying native file handle of the file this stream is reading
   * from
   *
   * @return A <code>FileDescriptor</code> for this stream
   *
   * @exception IOException If an error occurs
   */
  public final FileDescriptor getFD() throws IOException
  {
    synchronized (this)
      {
	if (fd == null)
	  fd = new FileDescriptor (ch);
	return fd;
      }
  }

  /**
   * This method reads an unsigned byte from the input stream and returns it
   * as an int in the range of 0-255.  This method also will return -1 if
   * the end of the stream has been reached.
   * <p>
   * This method will block until the byte can be read.
   *
   * @return The byte read or -1 if end of stream
   *
   * @exception IOException If an error occurs
   */
  public int read() throws IOException
  {
    return ch.read();
  }

  /**
   * This method reads bytes from a stream and stores them into a caller
   * supplied buffer.  This method attempts to completely fill the buffer,
   * but can return before doing so.  The actual number of bytes read is
   * returned as an int.  A -1 is returned to indicate the end of the stream.
   * <p>
   * This method will block until some data can be read.
   * <p>
   * This method operates by calling an overloaded read method like so:
   * <code>read(buf, 0, buf.length)</code>
   *
   * @param buf The buffer into which the bytes read will be stored.
   *
   * @return The number of bytes read or -1 if end of stream.
   *
   * @exception IOException If an error occurs.
   */
  public int read(byte[] buf) throws IOException
  {
    return read(buf, 0, buf.length);
  }

  /**
   * This method read bytes from a stream and stores them into a caller
   * supplied buffer.  It starts storing the data at index 
   * <code>offset</code> into
   * the buffer and attempts to read <code>len</code> bytes.  This method can
   * return before reading the number of bytes requested.  The actual number
   * of bytes read is returned as an int.  A -1 is returned to indicate the
   * end of the stream.
   * <p>
   * This method will block until some data can be read.
   *
   * @param buf The array into which the bytes read should be stored
   * @param offset The offset into the array to start storing bytes
   * @param len The requested number of bytes to read
   *
   * @return The actual number of bytes read, or -1 if end of stream.
   *
   * @exception IOException If an error occurs.
   */
  public int read(byte[] buf, int offset, int len) throws IOException
  {
    if (offset < 0
        || len < 0
        || offset + len > buf.length)
      throw new ArrayIndexOutOfBoundsException();

    return ch.read(ByteBuffer.wrap(buf, offset, len));
  }

  /**
   * This method skips the specified number of bytes in the stream.  It
   * returns the actual number of bytes skipped, which may be less than the
   * requested amount.
   * <p>
   * @param numBytes The requested number of bytes to skip
   *
   * @return The actual number of bytes skipped.
   *
   * @exception IOException If an error occurs
   */
  public synchronized long skip (long numBytes) throws IOException
  {
    if (numBytes < 0)
      throw new IllegalArgumentException ("Can't skip negative bytes: " + 
                                          numBytes);

    if (numBytes == 0)
      return 0;

    long oldPos = ch.position ();
    ch.position(oldPos + numBytes);
    return ch.position() - oldPos;
  }

  /**
   * This method creates a java.nio.channels.FileChannel.
   * Nio does not allow one to create a file channel directly.
   * A file channel must be created by first creating an instance of
   * Input/Output/RandomAccessFile and invoking the getChannel() method on it.
   */
  public synchronized FileChannel getChannel () 
  {
    return ch;
  }

} // class FileInputStream

