/* * Copyright (c) 2007, 2008, 2011, 2012, 2015 Eike Stepper (Berlin, Germany) and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Eike Stepper - initial API and implementation */ package org.eclipse.net4j.util.io; import java.io.IOException; import java.io.InputStream; /** * A <code>DelegatingInputStream</code> contains some other input stream, which it uses as its basic source of data, * possibly transforming the data along the way or providing additional functionality. The class * <code>DelegatingInputStream</code> itself simply overrides all (see note below) methods of <code>InputStream</code> * with versions that pass all requests to the contained input stream. Subclasses of <code>DelegatingInputStream</code> * may further override some of these methods and may also provide additional methods and fields. * <p> * <b>Note:</b> The only difference to {@link java.io.FilterInputStream} is that <code>DelegatingInputStream</code> does * <b>not</b> override {@link #read(byte[])} or {@link #read(byte[], int, int)} but rather exposes the original * implementations of <code>InputStream</code> which call {@link #read()} instead of their delegate counterparts. * * @author Eike Stepper */ public class DelegatingInputStream extends InputStream { /** * The input stream to be filtered. */ protected volatile InputStream in; /** * Creates a <code>DelegatingInputStream</code> by assigning the argument <code>in</code> to the field * <code>this.in</code> so as to remember it for later use. * * @param in * the underlying input stream, or <code>null</code> if this instance is to be created without an underlying * stream. */ protected DelegatingInputStream(InputStream in) { this.in = in; } public InputStream getDelegate() { return in; } /** * Reads the next byte of data from this input stream. The value byte is returned as an <code>int</code> in the range * <code>0</code> to <code>255</code>. If no byte is available because the end of the stream has been reached, the * value <code>-1</code> is returned. This method blocks until input data is available, the end of the stream is * detected, or an exception is thrown. * <p> * This method simply performs <code>in.read()</code> and returns the result. * * @return the next byte of data, or <code>-1</code> if the end of the stream is reached. * @exception IOException * if an I/O error occurs. * @see DelegatingInputStream#in */ @Override public int read() throws IOException { return in.read(); } /** * Skips over and discards <code>n</code> bytes of data from the input stream. The <code>skip</code> method may, for a * variety of reasons, end up skipping over some smaller number of bytes, possibly <code>0</code>. The actual number * of bytes skipped is returned. * <p> * This method simply performs <code>in.skip(n)</code>. * * @param n * the number of bytes to be skipped. * @return the actual number of bytes skipped. * @exception IOException * if an I/O error occurs. */ @Override public long skip(long n) throws IOException { return in.skip(n); } /** * Returns the number of bytes that can be read from this input stream without blocking. * <p> * This method simply performs <code>in.available()</code> and returns the result. * * @return the number of bytes that can be read from the input stream without blocking. * @exception IOException * if an I/O error occurs. * @see DelegatingInputStream#in */ @Override public int available() throws IOException { return in.available(); } /** * Closes this input stream and releases any system resources associated with the stream. This method simply performs * <code>in.close()</code>. * * @exception IOException * if an I/O error occurs. * @see DelegatingInputStream#in */ @Override public void close() throws IOException { in.close(); } /** * Marks the current position in this input stream. A subsequent call to the <code>reset</code> method repositions * this stream at the last marked position so that subsequent reads re-read the same bytes. * <p> * The <code>readlimit</code> argument tells this input stream to allow that many bytes to be read before the mark * position gets invalidated. * <p> * This method simply performs <code>in.mark(readlimit)</code>. * * @param readlimit * the maximum limit of bytes that can be read before the mark position becomes invalid. * @see DelegatingInputStream#in * @see DelegatingInputStream#reset() */ @Override public synchronized void mark(int readlimit) { in.mark(readlimit); } /** * Repositions this stream to the position at the time the <code>mark</code> method was last called on this input * stream. * <p> * This method simply performs <code>in.reset()</code>. * <p> * Stream marks are intended to be used in situations where you need to read ahead a little to see what's in the * stream. Often this is most easily done by invoking some general parser. If the stream is of the type handled by the * parse, it just chugs along happily. If the stream is not of that type, the parser should toss an exception when it * fails. If this happens within readlimit bytes, it allows the outer code to reset the stream and try another parser. * * @exception IOException * if the stream has not been marked or if the mark has been invalidated. * @see DelegatingInputStream#in * @see DelegatingInputStream#mark(int) */ @Override public synchronized void reset() throws IOException { in.reset(); } /** * Tests if this input stream supports the <code>mark</code> and <code>reset</code> methods. This method simply * performs <code>in.markSupported()</code>. * * @return <code>true</code> if this stream type supports the <code>mark</code> and <code>reset</code> method; * <code>false</code> otherwise. * @see DelegatingInputStream#in * @see java.io.InputStream#mark(int) * @see java.io.InputStream#reset() */ @Override public boolean markSupported() { return in.markSupported(); } }