alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/AutoCloseInputStream.java,v 1.7.2.1 2004/02/22 18:21:13 olegk Exp $
 * $Revision: 1.7.2.1 $
 * $Date: 2004/02/22 18:21:13 $
 *
 * ====================================================================
 *
 *  Copyright 2002-2004 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation.  For more
 * information on the Apache Software Foundation, please see
 * .
 *
 * [Additional notices, if required by prior licensing conditions]
 *
 */

package org.apache.commons.httpclient;

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * Closes an underlying stream as soon as the end of the stream is reached, and
 * notifies a client when it has done so.
 *
 * @author Ortwin Glück
 * @author Eric Johnson
 * @author Mike Bowler
 *
 * @since 2.0
 */

class AutoCloseInputStream extends FilterInputStream {

    /** 
     * True if this stream is open.  Assume that the underlying stream 
     * is open until we get an EOF indication.
     */
    private boolean streamOpen = true;

    /** True if the stream closed itself. */
    private boolean selfClosed = false;

    /** 
     * The watcher is notified when the contents of the stream have
     * been  exhausted
     */ 
    private ResponseConsumedWatcher watcher = null;

    /**
     * Create a new auto closing stream for the provided connection
     *
     * @param in the input stream to read from
     * @param watcher   To be notified when the contents of the stream have been
     *  consumed.
     */
    public AutoCloseInputStream(
            final InputStream in, final ResponseConsumedWatcher watcher) {
        super(in);
        this.watcher = watcher;
    }

    /**
     * Reads the next byte of data from the input stream.
     *
     * @throws IOException when there is an error reading
     * @return the character read, or -1 for EOF
     */
    public int read() throws IOException {
        int l = -1;

        if (isReadAllowed()) {
            // underlying stream not closed, go ahead and read.
            l = super.read();
            checkClose(l);
        }

        return l;
    }

    /**
     * Reads up to len bytes of data from the stream.
     *
     * @param b a byte array to read data into
     * @param off an offset within the array to store data
     * @param len the maximum number of bytes to read
     * @return the number of bytes read or -1 for EOF
     * @throws IOException if there are errors reading
     */
    public int read(byte[] b, int off, int len) throws IOException {
        int l = -1;

        if (isReadAllowed()) {
            l = super.read(b,  off,  len);
            checkClose(l);
        }

        return l;
    }

    /**
     * Reads some number of bytes from the input stream and stores them into the
     * buffer array b.
     *
     * @param b a byte array to read data into
     * @return the number of bytes read or -1 for EOF
     * @throws IOException if there are errors reading
     */
    public int read(byte[] b) throws IOException {
        int l = -1;

        if (isReadAllowed()) {
            l = super.read(b);
            checkClose(l);
        }
        return l;
    }

    /**
     * Close the stream, and also close the underlying stream if it is not
     * already closed.
     * @throws IOException If an IO problem occurs.
     */
    public void close() throws IOException {
        if (!selfClosed) {
            selfClosed = true;
            notifyWatcher();
        }
    }

    /**
     * Close the underlying stream should the end of the stream arrive.
     *
     * @param readResult    The result of the read operation to check.
     * @throws IOException If an IO problem occurs.
     */
    private void checkClose(int readResult) throws IOException {
        if (readResult == -1) {
            notifyWatcher();
        }
    }

    /**
     * See whether a read of the underlying stream should be allowed, and if
     * not, check to see whether our stream has already been closed!
     *
     * @return true if it is still OK to read from the stream.
     * @throws IOException If an IO problem occurs.
     */
    private boolean isReadAllowed() throws IOException {
        if (!streamOpen && selfClosed) {
            throw new IOException("Attempted read on closed stream.");
        }
        return streamOpen;
    }

    /**
     * Notify the watcher that the contents have been consumed.
     * @throws IOException If an IO problem occurs.
     */
    private void notifyWatcher() throws IOException {
        if (streamOpen) {
            super.close();
            streamOpen = false;

            if (watcher != null) {
                watcher.responseConsumed();
            }
        }
    }
}

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.