14fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy/*
24fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Licensed to the Apache Software Foundation (ASF) under one or more
34fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * contributor license agreements.  See the NOTICE file distributed with
44fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * this work for additional information regarding copyright ownership.
54fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * The ASF licenses this file to You under the Apache License, Version 2.0
64fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * (the "License"); you may not use this file except in compliance with
74fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * the License.  You may obtain a copy of the License at
84fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *
94fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *      http://www.apache.org/licenses/LICENSE-2.0
104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *
114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * Unless required by applicable law or agreed to in writing, software
124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * distributed under the License is distributed on an "AS IS" BASIS,
134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * See the License for the specific language governing permissions and
154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * limitations under the License.
164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */
174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedypackage org.apache.commons.io.input;
184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.EOFException;
204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.IOException;
214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedyimport java.io.InputStream;
224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy/**
244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * A functional, light weight {@link InputStream} that emulates
254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * a stream of a specified size.
264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p>
274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This implementation provides a light weight
284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * object for testing with an {@link InputStream}
294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * where the contents don't matter.
304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p>
314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * One use case would be for testing the handling of
324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * large {@link InputStream} as it can emulate that
334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * scenario without the overhead of actually processing
344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * large numbers of bytes - significantly speeding up
354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * test execution times.
364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <p>
374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * This implementation returns zero from the method that
384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * reads a byte and leaves the array unchanged in the read
394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * methods that are passed a byte array.
404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * If alternative data is required the <code>processByte()</code> and
414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <code>processBytes()</code> methods can be implemented to generate
424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * data, for example:
434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *
444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * <pre>
454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *  public class TestInputStream extends NullInputStream {
464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *      public TestInputStream(int size) {
474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *          super(size);
484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *      }
494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *      protected int processByte() {
504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *          return ... // return required value here
514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *      }
524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *      protected void processBytes(byte[] bytes, int offset, int length) {
534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *          for (int i = offset; i < length; i++) {
544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *              bytes[i] = ... // set array value here
554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *          }
564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *      }
574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *  }
584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * </pre>
594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy *
604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @since Commons IO 1.3
614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy * @version $Revision: 463529 $
624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy */
634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedypublic class NullInputStream extends InputStream {
644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    private long size;
664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    private long position;
674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    private long mark = -1;
684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    private long readlimit;
694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    private boolean eof;
704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    private boolean throwEofException;
714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    private boolean markSupported;
724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Create an {@link InputStream} that emulates a specified size
754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * which supports marking and does not throw EOFException.
764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param size The size of the input stream to emulate.
784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public NullInputStream(long size) {
804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy       this(size, true, false);
814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Create an {@link InputStream} that emulates a specified
854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * size with option settings.
864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param size The size of the input stream to emulate.
884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param markSupported Whether this instance will support
894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * the <code>mark()</code> functionality.
904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param throwEofException Whether this implementation
914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * will throw an {@link EOFException} or return -1 when the
924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * end of file is reached.
934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public NullInputStream(long size, boolean markSupported, boolean throwEofException) {
954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy       this.size = size;
964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy       this.markSupported = markSupported;
974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy       this.throwEofException = throwEofException;
984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
1004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
1014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Return the current position.
1024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
1034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @return the current position.
1044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
1054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public long getPosition() {
1064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        return position;
1074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
1084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
1094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
1104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Return the size this {@link InputStream} emulates.
1114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
1124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @return The size of the input stream to emulate.
1134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
1144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public long getSize() {
1154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        return size;
1164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
1174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
1184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
1194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Return the number of bytes that can be read.
1204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
1214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @return The number of bytes that can be read.
1224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
1234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public int available() {
1244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        long avail = size - position;
1254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        if (avail <= 0) {
1264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            return 0;
1274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        } else if (avail > Integer.MAX_VALUE) {
1284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            return Integer.MAX_VALUE;
1294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        } else {
1304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            return (int)avail;
1314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
1324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
1334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
1344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
1354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Close this input stream - resets the internal state to
1364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * the initial values.
1374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
1384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @throws IOException If an error occurs.
1394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
1404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public void close() throws IOException {
1414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        eof = false;
1424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        position = 0;
1434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        mark = -1;
1444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
1454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
1464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
1474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Mark the current position.
1484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
1494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param readlimit The number of bytes before this marked position
1504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * is invalid.
1514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @throws UnsupportedOperationException if mark is not supported.
1524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
1534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public synchronized void mark(int readlimit) {
1544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        if (!markSupported) {
1554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            throw new UnsupportedOperationException("Mark not supported");
1564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
1574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        mark = position;
1584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        this.readlimit = readlimit;
1594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
1604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
1614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
1624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Indicates whether <i>mark</i> is supported.
1634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
1644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @return Whether <i>mark</i> is supported or not.
1654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
1664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public boolean markSupported() {
1674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        return markSupported;
1684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
1694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
1704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
1714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Read a byte.
1724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
1734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @return Either The byte value returned by <code>processByte()</code>
1744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * or <code>-1</code> if the end of file has been reached and
1754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * <code>throwEofException</code> is set to <code>false</code>.
1764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @throws EOFException if the end of file is reached and
1774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * <code>throwEofException</code> is set to <code>true</code>.
1784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @throws IOException if trying to read past the end of file.
1794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
1804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public int read() throws IOException {
1814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        if (eof) {
1824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            throw new IOException("Read after end of file");
1834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
1844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        if (position == size) {
1854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            return doEndOfFile();
1864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
1874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        position++;
1884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        return processByte();
1894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
1904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
1914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
1924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Read some bytes into the specified array.
1934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
1944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param bytes The byte array to read into
1954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @return The number of bytes read or <code>-1</code>
1964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * if the end of file has been reached and
1974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * <code>throwEofException</code> is set to <code>false</code>.
1984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @throws EOFException if the end of file is reached and
1994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * <code>throwEofException</code> is set to <code>true</code>.
2004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @throws IOException if trying to read past the end of file.
2014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
2024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public int read(byte[] bytes) throws IOException {
2034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        return read(bytes, 0, bytes.length);
2044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
2054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
2064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
2074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Read the specified number bytes into an array.
2084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
2094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param bytes The byte array to read into.
2104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param offset The offset to start reading bytes into.
2114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param length The number of bytes to read.
2124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @return The number of bytes read or <code>-1</code>
2134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * if the end of file has been reached and
2144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * <code>throwEofException</code> is set to <code>false</code>.
2154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @throws EOFException if the end of file is reached and
2164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * <code>throwEofException</code> is set to <code>true</code>.
2174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @throws IOException if trying to read past the end of file.
2184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
2194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public int read(byte[] bytes, int offset, int length) throws IOException {
2204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        if (eof) {
2214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            throw new IOException("Read after end of file");
2224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
2234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        if (position == size) {
2244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            return doEndOfFile();
2254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
2264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        position += length;
2274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        int returnLength = length;
2284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        if (position > size) {
2294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            returnLength = length - (int)(position - size);
2304fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            position = size;
2314fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
2324fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        processBytes(bytes, offset, returnLength);
2334fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        return returnLength;
2344fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
2354fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
2364fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
2374fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Reset the stream to the point when mark was last called.
2384fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
2394fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @throws UnsupportedOperationException if mark is not supported.
2404fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @throws IOException If no position has been marked
2414fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * or the read limit has been exceed since the last position was
2424fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * marked.
2434fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
2444fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public synchronized void reset() throws IOException {
2454fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        if (!markSupported) {
2464fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            throw new UnsupportedOperationException("Mark not supported");
2474fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
2484fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        if (mark < 0) {
2494fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            throw new IOException("No position has been marked");
2504fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
2514fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        if (position > (mark + readlimit)) {
2524fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            throw new IOException("Marked position [" + mark +
2534fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    "] is no longer valid - passed the read limit [" +
2544fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy                    readlimit + "]");
2554fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
2564fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        position = mark;
2574fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        eof = false;
2584fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
2594fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
2604fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
2614fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Skip a specified number of bytes.
2624fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
2634fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param numberOfBytes The number of bytes to skip.
2644fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @return The number of bytes skipped or <code>-1</code>
2654fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * if the end of file has been reached and
2664fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * <code>throwEofException</code> is set to <code>false</code>.
2674fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @throws EOFException if the end of file is reached and
2684fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * <code>throwEofException</code> is set to <code>true</code>.
2694fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @throws IOException if trying to read past the end of file.
2704fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
2714fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    public long skip(long numberOfBytes) throws IOException {
2724fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        if (eof) {
2734fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            throw new IOException("Skip after end of file");
2744fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
2754fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        if (position == size) {
2764fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            return doEndOfFile();
2774fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
2784fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        position += numberOfBytes;
2794fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        long returnLength = numberOfBytes;
2804fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        if (position > size) {
2814fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            returnLength = numberOfBytes - (position - size);
2824fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            position = size;
2834fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
2844fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        return returnLength;
2854fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
2864fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
2874fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
2884fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Return a byte value for the  <code>read()</code> method.
2894fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * <p>
2904fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * This implementation returns zero.
2914fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
2924fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @return This implementation always returns zero.
2934fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
2944fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    protected int processByte() {
2954fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        // do nothing - overridable by subclass
2964fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        return 0;
2974fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
2984fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
2994fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
3004fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Process the bytes for the <code>read(byte[], offset, length)</code>
3014fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * method.
3024fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * <p>
3034fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * This implementation leaves the byte array unchanged.
3044fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
3054fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param bytes The byte array
3064fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param offset The offset to start at.
3074fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @param length The number of bytes.
3084fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
3094fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    protected void processBytes(byte[] bytes, int offset, int length) {
3104fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        // do nothing - overridable by subclass
3114fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
3124fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
3134fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    /**
3144fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * Handle End of File.
3154fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     *
3164fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @return <code>-1</code> if <code>throwEofException</code> is
3174fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * set to <code>false</code>
3184fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * @throws EOFException if <code>throwEofException</code> is set
3194fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     * to <code>true</code>.
3204fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy     */
3214fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    private int doEndOfFile() throws EOFException {
3224fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        eof = true;
3234fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        if (throwEofException) {
3244fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy            throw new EOFException();
3254fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        }
3264fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy        return -1;
3274fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy    }
3284fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy
3294fa0a3295bcacbdcd6a9e7709cf17aa5adb90356Scott Kennedy}
330