FileDescriptor.
 *
 * @author Aaron M. Renn FileOutputStream object to write
   * to the named file.  The file is created if it does not exist, and
   * the bytes written are written starting at the beginning of the file if
   * the append argument is false or at the end
   * of the file if the append argument is true.
   * 
   * Before opening a file, a security check is performed by calling the
   * checkWrite method of the SecurityManager (if
   * one exists) with the name of the file to be opened.  An exception is
   * thrown if writing is not allowed. 
   *
   * @param name The name of the file this stream should write to
   * @param append true to append bytes to the end of the file,
   * or false to write bytes to the beginning
   *
   * @exception SecurityException If write access to the file is not allowed
   * @exception FileNotFoundException If a non-security error occurs
   */
  public FileOutputStream (String path, boolean append)
    throws SecurityException, FileNotFoundException
  {
    SecurityManager s = System.getSecurityManager();
    if (s != null)
      s.checkWrite(path);
    fd = new FileDescriptor (path, (append
				    ? FileDescriptor.WRITE
				      | FileDescriptor.APPEND
				    : FileDescriptor.WRITE));
  }
  /**
   * This method initializes a FileOutputStream object to write
   * to the named file.  The file is created if it does not exist, and
   * the bytes written are written starting at the beginning of the file.
   * 
   * Before opening a file, a security check is performed by calling the
   * checkWrite method of the SecurityManager (if
   * one exists) with the name of the file to be opened.  An exception is
   * thrown if writing is not allowed. 
   *
   * @param name The name of the file this stream should write to
   *
   * @exception SecurityException If write access to the file is not allowed
   * @exception FileNotFoundException If a non-security error occurs
   */
  public FileOutputStream (String path)
    throws SecurityException, FileNotFoundException
  {
    this (path, false);
  }
  /**
   * This method initializes a FileOutputStream object to write
   * to the specified File object.  The file is created if it 
   * does not exist, and the bytes written are written starting at the 
   * beginning of the file.
   * 
   * Before opening a file, a security check is performed by calling the
   * checkWrite method of the SecurityManager (if
   * one exists) with the name of the file to be opened.  An exception is
   * thrown if writing is not allowed. 
   *
   * @param file The File object this stream should write to
   *
   * @exception SecurityException If write access to the file is not allowed
   * @exception FileNotFoundException If a non-security error occurs
   */
  public FileOutputStream (File file)
    throws SecurityException, FileNotFoundException
  {
    this (file.getPath(), false);
  }
  /**
   * This method initializes a FileOutputStream object to write
   * to the specified File object.  The file is created if it 
   * does not exist, and the bytes written are written starting at the 
   * beginning of the file if the append parameter is 
   * false.  Otherwise bytes are written at the end of the
   * file.
   * 
   * Before opening a file, a security check is performed by calling the
   * checkWrite method of the SecurityManager (if
   * one exists) with the name of the file to be opened.  An exception is
   * thrown if writing is not allowed. 
   *
   * @param file The File object this stream should write to
   * @param append true to append bytes to the end of the file,
   * or false to write bytes to the beginning
   *
   * @exception SecurityException If write access to the file is not allowed
   * @exception FileNotFoundException If a non-security error occurs
   */
  public FileOutputStream (File file, boolean append)
    throws FileNotFoundException
  {
    this (file.getPath(), append);
  }
  /**
   * This method initializes a FileOutputStream object to write
   * to the file represented by the specified FileDescriptor
   * object.  This method does not create any underlying disk file or
   * reposition the file pointer of the given descriptor.  It assumes that
   * this descriptor is ready for writing as is.
   * 
   * Before opening a file, a security check is performed by calling the
   * checkWrite method of the SecurityManager (if
   * one exists) with the specified FileDescriptor as an argument.
   * An exception is thrown if writing is not allowed. 
   *
   * @param file The FileDescriptor this stream should write to
   *
   * @exception SecurityException If write access to the file is not allowed
   */
  public FileOutputStream (FileDescriptor fdObj)
    throws SecurityException
  {
    // Hmm, no other exception but this one to throw, but if the descriptor
    // isn't valid, we surely don't have "permission" to write to it.
    if (!fdObj.valid())
      throw new SecurityException("Invalid FileDescriptor");
    SecurityManager s = System.getSecurityManager();
    if (s != null)
      s.checkWrite(fdObj);
    fd = fdObj;
  }
  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 FileDescriptor object representing
   * the file that is currently being written to
   *
   * @return A FileDescriptor object for this stream
   *
   * @exception IOException If an error occurs
   */
  public final FileDescriptor getFD () throws IOException
  {
    if (! fd.valid())
      throw new IOException ();
    return fd;
  }
  /**
   * This method writes a single byte of data to the file.  
   *
   * @param b The byte of data to write, passed as an int
   *
   * @exception IOException If an error occurs
   */
  public void write (int b) throws IOException
  {
    fd.write (b);
  }
  /**
   * This method writes all the bytes in the specified array to the
   * file.
   *
   * @param buf The array of bytes to write to the file
   *
   * @exception IOException If an error occurs
   */
  public void write (byte[] buf)
    throws IOException
  {
    write (buf, 0, buf.length);
  }
  /**
   * This method writes len bytes from the byte array 
   * buf to the file starting at index offset.
   *
   * @param buf The array of bytes to write to the file
   * @param offset The offset into the array to start writing bytes from
   * @param len The number of bytes to write to the file
   *
   * @exception IOException If an error occurs
   */
  public void write (byte[] buf, int offset, int len)
    throws IOException
  {
    if (offset < 0
        || len < 0
        || offset + len > buf.length)
      throw new ArrayIndexOutOfBoundsException ();
    
    fd.write (buf, offset, len);
  }
  /**
   * This method closes the underlying file.  Any further attempts to
   * write to this stream will likely generate an exception since the
   * file is closed.
   *
   * @exception IOException If an error occurs
   */
  public void close () throws IOException
  {
    if (fd.valid())
      fd.close();
  }
  /**
   * 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() 
  {
    if (ch == null)
      ch = new FileChannelImpl (fd, true, this);
    return ch;
  }
} // class FileOutputStream