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

  $Archive: /njcl_v2/src/com/novell/java/io/NOutputStream.java $
  $Revision: 6 $
  $Modtime: 1/18/00 9:16a $
 
  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.OutputStreamNotSupportedException;

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

/**
 * Provides output stream functionality to various data device objects,
 * which implements the DataAccessable interface.
 *
 * <p>The various constructors open an output 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 only support a stream to itself. The constructors with a name 
 * parameter (which must be atomic) 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>There is also a set of constructors that support 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 == WRITE). See Novell's 
 * DataAccessableParameters and NFileOutputStream for an example of how a 
 * provider might implement this support.</p>
 *
 * <p>NoSubordinateAccessException will be thrown if the given DataAccessable
 * object does not support subordinate streams (subordinate constructors).
 * SubordinateAccessOnlyException will be thrown if the given 
 * DataAccessable object does not support a stream on itself.
 *
 * @see DataAccessable
 * @see NInputStream
 * @see RandomAccess
 * @see com.novell.service.file.nw.NFileOutputStream
 * @see com.novell.service.file.nw.DataAccessableParameters
 */

public class NOutputStream extends java.io.OutputStream
{
   private DataAccessor stream;

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

   /**
    * Creates an instance of the NOutputStream object.
    * 
    * <p>Opens an output 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 OutputStreamNotSupportedException If the accessor does not
    *            support an output stream.
    */
    
   public NOutputStream(DataAccessable accessor)
      throws IOException
   {
      stream = accessor.openStream(DataAccessor.WRITE);
   }

   /**
    * Creates an instance of the NOutputStream object with the custom
    * parameter to the accessor.
    * 
    * <p>Opens an output 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   The 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 OutputStreamNotSupportedException If the accessor does not
    *            support an output stream.
    *
    * @exception IllegalArgumentException If the custom object is not of
    *            the expected type for the given provider.
    */
    
   public NOutputStream(
      DataAccessable accessor, 
      Object custom)
      throws IOException
   {
      stream = accessor.openStream(DataAccessor.WRITE, custom);
   }

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

   /**
    * Creates a subordinate instance of the NOutputStream.
    * 
    * <p>Opens a subordinate output 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; for example, a file.
    *
    * @exception OutputStreamNotSupportedException If the accessor does not
    *            support an output stream.
    */
    
   public NOutputStream(String name, DataAccessable accessor)
      throws IOException
   {
      stream = accessor.openStream(name, DataAccessor.WRITE);
   }

   /**
    * Creates a subordinate instance of an NOutputStream with the custom
    * parameter.
    * 
    * <p>Opens a subordinate output 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   The 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; for example, a file.
    *
    * @exception OutputStreamNotSupportedException If the accessor does not
    *            support an output stream.
    *
    * @exception IllegalArgumentException If the custom object is not of
    *            the expected type for the given provider.
    */
    
   public NOutputStream(
      String name,
      DataAccessable accessor, 
      Object custom)
      throws IOException
   {
      stream = accessor.openStream(name, DataAccessor.WRITE, custom);
   }

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

   protected NOutputStream()
   {
   }

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

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

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

   /**
    * Makes sure that all output is written.
    *
    * @exception IOException When an I/O error occurs.
    */
   public void flush()
      throws IOException
   {
      stream.flush();
   }

   /**
    * Writes one byte.
    *
    * @param b The byte to write.
    *
    * @exception IOException When an I/O error occurs.
    */
   public void write(int b)
      throws IOException
   {
      stream.write(b);
   }

   /**
    * Writes an array of bytes.
    *
    * <p>All bytes in the array are written.</p>
    *
    * @param b The array of bytes to write.
    *
    * @exception IOException When an I/O error occurs.
    */
   public void write(byte[] b)
      throws IOException
   {
      stream.write(b);
   }

   /**
    * Writes a subset of an array of bytes.
    *
    * @param b   The array of bytes to write.
    * @param off The offset from which to start writing.
    * @param len The number of bytes to write.
    *
    * @exception IOException When an I/O error occurs.
    */
   public void write(byte[] b, int off, int len)
      throws IOException
   {
      stream.write(b, off, len);
   }

   /**
    * Sets the DataAccessor to be used by the methods in this class.
    *
    * <p>It is used by the sub-classes of NWOutputStream to set the
    * DataAccessor to be used by the methods in this class. 
    * setDataAccessor() should be used only by SPI developers.
    *
    * @param da The DataAccessor to be set.
    */

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