/*
 * @(#)DigestOutputStream.java	1.20 97/08/07
 * 
 * Copyright 1993-1997 Sun Microsystems, Inc. 901 San Antonio Road, 
 * Palo Alto, California, 94303, U.S.A.  All Rights Reserved.
 * 
 * This software is the confidential and proprietary information of Sun
 * Microsystems, Inc. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Sun.
 * 
 * CopyrightVersion 1.2
 * 
 */

package com.novell.java.security;

import java.io.IOException;
import java.io.EOFException;
import java.io.OutputStream;
import java.io.FilterOutputStream;
import java.io.PrintStream;
import java.io.ByteArrayOutputStream;

/**
 * Provides a transparent stream that updates the associated message
 * digest using the bits going through the stream. To complete the
 * message digest computation, call one of the digest methods on the
 * associated message digest after calling one of this digest ouput
 * stream's write() methods.
 *      
 * <p>It is possible to turn this stream ON or OFF by calling the on()
 * method. When it is ON, a call to write() results in an update on
 * the message digest. When the output stream is OFF, the message 
 * digest is not updated. The default is for the stream to be ON.
 *
 * @see MessageDigest
 * @see DigestInputStream
 *
 * @version 1.20 98/01/14
 * @author Benjamin Renaud */

public class DigestOutputStream extends FilterOutputStream {
  
    private boolean on = true;

    /**
     * @internal
     *  
     * The message digest associated with this stream.  
     */  
    protected MessageDigest digest;

    /**
     * Creates a digest output stream using the specified output
     * stream and message digest.
     *
     * @param stream The output stream.
     *
     * @param digest The message digest to associate with this stream.
     */
    public DigestOutputStream(OutputStream stream, MessageDigest digest) {
	super(stream);
	setMessageDigest(digest);
    }

    /**
     * Returns the message digest associated with this stream.
     *
     * @return The message digest associated with this stream.
     */
    public MessageDigest getMessageDigest() {
	return digest;
    }    

    /**
     * Associates the specified message digest with this stream.
     *
     * @param digest The message digest to be associated with this
     *               stream.  
     */
    public void setMessageDigest(MessageDigest digest) {
	this.digest = digest;
    }

    /**
     * Updates the message digest using the specified byte. The
     * update is done only if the digest function is ON. Following
     * the update the byte is written to the output stream. If the
     * digest function is set to ON by the on() method, the write
     * method calls the update() method on the message digest
     * associated with this stream, passing it the byte b. The byte
     * is then written  to the output stream, blocking until the byte 
     * is actually written.
     *
     * @param b The byte to be used for updating and writing to the    
     *          output stream.    
     *
     * @exception IOException Thrown if an I/O error occurs.
     * 
     * @see MessageDigest#update(byte) 
     */
    public void write(int b) throws IOException {
	if (on) {
	    digest.update((byte)b);
	}
	out.write(b);
    }

    /**
     * Updates the message digest using the specified subarray,
     * and writes the subarray to the output stream. The update is
     * done only if the digest function is set to ON by calling
     * the on() method. That is, if the digest function is ON, this
     * write() method calls update() on the message digest associated
     * with this stream, passing it the subarray specifications.
     * This write() method then writes the subarray bytes to the
     * output stream, blocking until the bytes are actually written.
     *
     * @param b The array containing the subarray to be used for
     * updating and writing to the output stream.
     *
     * @param off The offset into the byte array (b[]) of the first
     * byte to be updated and written.
     *
     * @param len The number of bytes of data to be updated and written 
     * from the byte array (b[]), starting at offset specified by
     * the off parameter.
     *
     * @exception IOException if an I/O error occurs.
     * 
     * @see MessageDigest#update(byte[], int, int)
     */
    public void write(byte[] b, int off, int len) throws IOException {
	if (on) {
	    digest.update(b, off, len);
	}
	out.write(b, off, len);
    }

    /**
     * Turns the digest function ON (default) or OFF. When it is on,
     * a call to the write() function results in an update on the
     * message digest. When the digest function is OFF the message
     * digest is not updated.
     *    
     * @param on A boolean set to TRUE to turn the digest function ON,
     *           and FALSE to turn it OFF.
     */
    public void on(boolean on) {
	this.on = on;
    }
	
    /**
     * Prints a String representation of this digest output stream and
     * its associated message digest object.  
     */
     public String toString() {
	 return "[Digest Output Stream] " + digest.toString();
     }
}	


  

