/* **************************************************************************

  $Archive: /njcl_v2/src/com/novell/java/io/NInputStream.java $
  $Revision: 4 $
  $Modtime: 1/18/00 9:14a $
 
  Copyright (c) 1998 Novell, Inc.  All Rights Reserved.

  THIS WORK IS  SUBJECT  TO  U.S.  AND  INTERNATIONAL  COPYRIGHT  LAWS  AND
  TREATIES.   NO  PART  OF  THIS  WORK MAY BE  USED,  PRACTICED,  PERFORMED
  COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED,  ABRIDGED, CONDENSED,
  EXPANDED,  COLLECTED,  COMPILED,  LINKED,  RECAST, TRANSFORMED OR ADAPTED
  WITHOUT THE PRIOR WRITTEN CONSENT OF NOVELL, INC. ANY USE OR EXPLOITATION
  OF THIS WORK WITHOUT AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO
  CRIMINAL AND CIVIL LIABILITY.

****************************************************************************/

package com.novell.java.io;

import java.io.IOException;

import com.novell.java.io.SubordinateAccessOnlyException;
import com.novell.java.io.NoSubordinateAccessException;
import com.novell.java.io.InputStreamNotSupportedException;

import com.novell.java.io.spi.DataAccessor;

/**
 * Provides input stream functionality to various data device object,
 * which implements the DataAccessable interface.
 *
 * <p>The various constructors open an input stream on (or with) the 
 * DataAccessable object passed into the constructors. The DataAccessable
 * object might have container capabilities and support subordinate
 * streams, or it may support only a stream to itself. The constructors
 * with a name parameter (which must be atomic) will attempt to open a
 * subordinate stream through the given DataAccessable object. The
 * constructors without a name parameter attempt to open a stream on
 * the given DataAcessable object.
 *
 * <p>A set of constructors is provided for the support of provider
 * based custom parameters. A given implementation of a DataAccessable
 * object might require custom parameters to open the stream. For example,
 * a file system provider might require open flags, fork selectors,
 * name space information, size, and so forth, to open the stream.
 * The custom Object parameter allows for passing known provider-supplied
 * objects to their DataAccessable implementations, allowing
 * the user full control over the opening of the stream if needed.
 * The various providers must implement reasonable defaults for any
 * custom parameters if the non-custom constructors are used
 * (open flags == READ). See Novell's DataAccessableParameters and
 * NFileInputStream for an example of how a provider might implement
 * this support.
 *
 * <p>A NoSubordinateAccessException will be thrown if the given
 * DataAccessable object does not support subordinate streams
 * (subordinate constructors). A SubordinateAccessOnlyException
 * will be thrown if the given DataAccessable object does not support
 * a stream on itself. 
 * </p>
 *
 * @see com.novell.java.io.DataAccessable
 * @see com.novell.java.io.NOutputStream
 * @see com.novell.java.io.RandomAccess
 * @see com.novell.service.file.nw.NFileInputStream
 * @see com.novell.service.file.nw.DataAccessableParameters
 */

public class NInputStream extends java.io.InputStream
{
   private DataAccessor stream;

/* **************************************************************************
   non-subordinate stream
****************************************************************************/

   /**
    * Creates an instance of the NInputStream.
    * 
    * <p>Opens an input stream to the DataAccessable accessor parameter.</p>
    *
    * @param accessor The DataAccessable object to use.
    *
    * @exception IOException If the stream cannot be opened.
    *
    * @exception SubordinateAccessOnlyException If the accessor does not
    *            support a stream to itself, for example, a directory.
    *
    * @exception InputStreamNotSupportedException If the accessor does not
    *            support an input stream.
    */
    
   public NInputStream(DataAccessable accessor)
      throws IOException
   {
      stream = accessor.openStream(DataAccessor.READ);
   }

   /**
    * Creates an instance of NInputStream with the custom parameter.
    * 
    * <p>Opens an input stream to the DataAccessable accessor parameter, 
    * passing the provider-based custom parameter to the accessor for the 
    * open.</p>
    *
    * @param accessor The DataAccessable object to use.
    *
    * @param custom  Provider-specific custom object containing 
    *                any needed parameters to open the stream.
    *
    * @exception SubordinateAccessOnlyException If the accessor does not
    *             support a stream to itself, for example, a directory.
    *
    * @exception InputStreamNotSupportedException If the accessor does not
    *            support an input stream.
    *
    * @exception IllegalArgumentException If the custom object is not of
    *            the expected type for the given provider.
    */
    
   public NInputStream(DataAccessable accessor, Object custom)
      throws IOException
   {
      stream = accessor.openStream(DataAccessor.READ, custom);
   }

/* **************************************************************************
   subordinate stream
****************************************************************************/

   /**
    * Creates a subordinate instance of NInputStream.
    * 
    * <p>Opens a subordinate input stream to the DataAccessable accessor 
    * parameter.</p>
    *
    * @param name The atomic subordinate stream name to open.
    *
    * @param accessor The DataAccessable object to use.
    *
    * @exception IOException If the stream cannot be opened.
    *
    * @exception NoSubordinateAccessException If the accessor does not
    *            support opening a subordinate stream.
    *
    * @exception InputStreamNotSupportedException If the accessor does not
    *            support an input stream.
    */
    
   public NInputStream(String name, DataAccessable accessor)
      throws IOException
   {
      stream = accessor.openStream(name, DataAccessor.READ);
   }

   /**
    * Creates a subordinate instance of NInputStream with the custom parameter.
    * 
    * <p>Opens a subordinate input stream to the DataAccessable accessor 
    * parameter, passing the provider based custom parameter to the accessor 
    * for the open.</p>
    *
    * @param name     The atomic subordinate stream name to open.
    *
    * @param accessor The DataAccessable object to use.
    *
    * @param custom   Provider-specific custom object containing 
    *                 any needed parameters to open the stream.
    *
    * @exception IOException If the stream cannot be opened.
    *
    * @exception NoSubordinateAccessException If the accessor does not
    *            support opening a subordinate stream.
    *
    * @exception InputStreamNotSupportedException If the accessor does not
    *            support an input stream.
    *
    * @exception IllegalArgumentException If the custom object is not of
    *            the expected type for the given provider.
    */
    
   public NInputStream(
      String name,
      DataAccessable accessor, 
      Object custom)
      throws IOException
   {
      stream = accessor.openStream(name, DataAccessor.READ, custom);
   }

   /**
    * Provides a default constructor for subclass extension.
    *
    * <p>This constructor should not be used by the user application layer;
    * it is for SPI developers only.
    */

   protected NInputStream()
   {
   }

/* **************************************************************************
   Accessor methods
****************************************************************************/

   /**
    * Returns bytes that are available to read without blocking.
    *
    * @return Bytes that can be read without blocking.
    *
    * @exception IOException When an I/O error occurs.
    */

   public int available()
      throws IOException
   {
      return(stream.available());
   }

   /**
    * Closes the stream.
    *
    * @exception IOException When an I/O error occurs.
    */

   public void close()
      throws IOException
   {
      stream.close();
   }

   /**
    * Saves the current position, which can then be restored by calling
    * reset().
    *
    * <p>If markSupported() returns FALSE, mark() does nothing.</p>
    *
    * @param readLimit The limit to number of bytes that can
    *                  be read before the mark becomes invalid.
    */

   public void mark(int readLimit)
   {
      stream.mark(readLimit);
   }

   /**
    * Determines whether the mark() and reset() methods are valid
    * for the stream.
    *
    * @return A boolean set to TRUE if mark() and reset() are valid
    *         for this stream, otherwise FALSE is returned.
    */

   public boolean markSupported()
   {
      return(stream.markSupported());
   }

   /**
    * Reads a byte.
    *
    * @return The byte read.  -1 is returned if there are no more
    *         bytes to read in the stream.
    *
    * @exception IOException When an I/O error occurs.
    */

   public int read()
      throws IOException
   {
      return(stream.read());
   }

   /**
    * Reads an array of bytes.
    *
    * @param  b The array into which to read the bytes.
    *
    * @return The number of bytes read, or if there were no bytes available
    *         to read, -1 is returned. If 'b' is zero bytes long, 0 is
    *         returned.
    *
    * @exception IOException When an I/O error occurs.
    */
   public int read (byte[] b)
      throws IOException
   {
      return(stream.read(b));
   }

   /**
    * Reads the specified number of bytes into an array.
    *
    * @param  b    The array into which to read the bytes.
    * @param  off The offset in 'b' at which to start storing the
    *             bytes read.
    * @param  len The number of bytes to read. At most, this number
    *             of bytes will be read, but it could be less.
    *
    * @return The number of bytes read, or -1/ is returned if there
    *         were no bytes available to read. If 'len' is zero,
    *         0 is returned.
    *
    * @exception IOException When an I/O error occurs.
    */
   public int read(byte[] b, int off, int len)
      throws IOException
   {
      return(stream.read(b, off, len));
   }

   /**
    * Resets the stream position to the last position saved by calling
    * mark().
    *
    * @exception IOException If mark() and reset() are not supported or
    *                        when an I/O error occurs.
    */

   public void reset()
      throws IOException
   {
      stream.reset();
   }

   /**
    * Skips the specified number of bytes.
    *
    * @param  n The number of bytes to skip.
    *
    * @return The number of bytes skipped or -1 if already
    *         at the end of the stream.
    *
    * @exception IOException When an I/O error occurs.
    */

   public long skip(long n)
      throws IOException
   {
      return(stream.skip(n));
   }

   /**
    * Sets the DataAccessor to be used by the methods in this class.
    *
    * <p>This method is used by the sub-classes of NWInputStream to
    * set the DataAccessor to be used by the methods in this class.
    * It is used by SPI developers only.
    *
    * @param da The DataAccessor to be used.
    */

   protected void setDataAccessor(DataAccessor da)
   {
      stream = da;
   }
}
