1bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/*
2bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Licensed to the Apache Software Foundation (ASF) under one or more
3bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * contributor license agreements.  See the NOTICE file distributed with
4bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * this work for additional information regarding copyright ownership.
5bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * The ASF licenses this file to You under the Apache License, Version 2.0
6bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * (the "License"); you may not use this file except in compliance with
7bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * the License.  You may obtain a copy of the License at
8bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
9bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *      http://www.apache.org/licenses/LICENSE-2.0
10bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
11bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Unless required by applicable law or agreed to in writing, software
12bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * distributed under the License is distributed on an "AS IS" BASIS,
13bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * See the License for the specific language governing permissions and
15bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * limitations under the License.
16bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */
17bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpackage org.apache.commons.io.input;
18bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
19bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.EOFException;
20bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.IOException;
21bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.InputStream;
22bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
23bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/**
24bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * A functional, light weight {@link InputStream} that emulates
25bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * a stream of a specified size.
26bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <p>
27bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * This implementation provides a light weight
28bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * object for testing with an {@link InputStream}
29bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * where the contents don't matter.
30bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <p>
31bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * One use case would be for testing the handling of
32bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * large {@link InputStream} as it can emulate that
33bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * scenario without the overhead of actually processing
34bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * large numbers of bytes - significantly speeding up
35bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * test execution times.
36bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <p>
37bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * This implementation returns zero from the method that
38bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * reads a byte and leaves the array unchanged in the read
39bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * methods that are passed a byte array.
40bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * If alternative data is required the <code>processByte()</code> and
41bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <code>processBytes()</code> methods can be implemented to generate
42bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * data, for example:
43bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
44bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <pre>
45bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *  public class TestInputStream extends NullInputStream {
46bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *      public TestInputStream(int size) {
47bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *          super(size);
48bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *      }
49bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *      protected int processByte() {
50bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *          return ... // return required value here
51bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *      }
52bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *      protected void processBytes(byte[] bytes, int offset, int length) {
53bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *          for (int i = offset; i < length; i++) {
54bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *              bytes[i] = ... // set array value here
55bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *          }
56bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *      }
57bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *  }
58bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * </pre>
59bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
60bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @since Commons IO 1.3
61bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @version $Revision: 463529 $
62bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */
63bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpublic class NullInputStream extends InputStream {
64bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
65bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private long size;
66bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private long position;
67bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private long mark = -1;
68bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private long readlimit;
69bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private boolean eof;
70bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private boolean throwEofException;
71bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private boolean markSupported;
72bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
73bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
74bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Create an {@link InputStream} that emulates a specified size
75bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * which supports marking and does not throw EOFException.
76bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
77bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param size The size of the input stream to emulate.
78bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
79bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public NullInputStream(long size) {
80bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook       this(size, true, false);
81bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
82bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
83bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
84bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Create an {@link InputStream} that emulates a specified
85bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * size with option settings.
86bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
87bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param size The size of the input stream to emulate.
88bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param markSupported Whether this instance will support
89bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * the <code>mark()</code> functionality.
90bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param throwEofException Whether this implementation
91bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * will throw an {@link EOFException} or return -1 when the
92bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * end of file is reached.
93bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
94bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public NullInputStream(long size, boolean markSupported, boolean throwEofException) {
95bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook       this.size = size;
96bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook       this.markSupported = markSupported;
97bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook       this.throwEofException = throwEofException;
98bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
99bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
100bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
101bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Return the current position.
102bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
103bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return the current position.
104bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
105bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public long getPosition() {
106bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return position;
107bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
108bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
109bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
110bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Return the size this {@link InputStream} emulates.
111bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
112bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return The size of the input stream to emulate.
113bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
114bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public long getSize() {
115bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return size;
116bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
117bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
118bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
119bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Return the number of bytes that can be read.
120bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
121bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return The number of bytes that can be read.
122bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
123bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public int available() {
124bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        long avail = size - position;
125bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (avail <= 0) {
126bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return 0;
127bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else if (avail > Integer.MAX_VALUE) {
128bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return Integer.MAX_VALUE;
129bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        } else {
130bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return (int)avail;
131bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
132bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
133bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
134bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
135bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Close this input stream - resets the internal state to
136bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * the initial values.
137bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
138bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws IOException If an error occurs.
139bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
140bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void close() throws IOException {
141bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        eof = false;
142bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        position = 0;
143bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mark = -1;
144bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
145bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
146bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
147bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Mark the current position.
148bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
149bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param readlimit The number of bytes before this marked position
150bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * is invalid.
151bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws UnsupportedOperationException if mark is not supported.
152bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
153bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public synchronized void mark(int readlimit) {
154bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (!markSupported) {
155bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            throw new UnsupportedOperationException("Mark not supported");
156bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
157bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        mark = position;
158bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        this.readlimit = readlimit;
159bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
160bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
161bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
162bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Indicates whether <i>mark</i> is supported.
163bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
164bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return Whether <i>mark</i> is supported or not.
165bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
166bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public boolean markSupported() {
167bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return markSupported;
168bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
169bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
170bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
171bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Read a byte.
172bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
173bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return Either The byte value returned by <code>processByte()</code>
174bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * or <code>-1</code> if the end of file has been reached and
175bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * <code>throwEofException</code> is set to <code>false</code>.
176bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws EOFException if the end of file is reached and
177bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * <code>throwEofException</code> is set to <code>true</code>.
178bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws IOException if trying to read past the end of file.
179bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
180bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public int read() throws IOException {
181bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (eof) {
182bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            throw new IOException("Read after end of file");
183bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
184bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (position == size) {
185bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return doEndOfFile();
186bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
187bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        position++;
188bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return processByte();
189bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
190bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
191bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
192bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Read some bytes into the specified array.
193bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
194bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param bytes The byte array to read into
195bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return The number of bytes read or <code>-1</code>
196bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * if the end of file has been reached and
197bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * <code>throwEofException</code> is set to <code>false</code>.
198bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws EOFException if the end of file is reached and
199bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * <code>throwEofException</code> is set to <code>true</code>.
200bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws IOException if trying to read past the end of file.
201bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
202bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public int read(byte[] bytes) throws IOException {
203bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return read(bytes, 0, bytes.length);
204bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
205bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
206bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
207bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Read the specified number bytes into an array.
208bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
209bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param bytes The byte array to read into.
210bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param offset The offset to start reading bytes into.
211bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param length The number of bytes to read.
212bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return The number of bytes read or <code>-1</code>
213bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * if the end of file has been reached and
214bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * <code>throwEofException</code> is set to <code>false</code>.
215bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws EOFException if the end of file is reached and
216bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * <code>throwEofException</code> is set to <code>true</code>.
217bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws IOException if trying to read past the end of file.
218bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
219bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public int read(byte[] bytes, int offset, int length) throws IOException {
220bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (eof) {
221bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            throw new IOException("Read after end of file");
222bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
223bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (position == size) {
224bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return doEndOfFile();
225bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
226bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        position += length;
227bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        int returnLength = length;
228bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (position > size) {
229bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            returnLength = length - (int)(position - size);
230bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            position = size;
231bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
232bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        processBytes(bytes, offset, returnLength);
233bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return returnLength;
234bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
235bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
236bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
237bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Reset the stream to the point when mark was last called.
238bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
239bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws UnsupportedOperationException if mark is not supported.
240bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws IOException If no position has been marked
241bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * or the read limit has been exceed since the last position was
242bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * marked.
243bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
244bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public synchronized void reset() throws IOException {
245bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (!markSupported) {
246bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            throw new UnsupportedOperationException("Mark not supported");
247bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
248bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (mark < 0) {
249bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            throw new IOException("No position has been marked");
250bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
251bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (position > (mark + readlimit)) {
252bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            throw new IOException("Marked position [" + mark +
253bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    "] is no longer valid - passed the read limit [" +
254bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                    readlimit + "]");
255bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
256bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        position = mark;
257bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        eof = false;
258bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
259bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
260bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
261bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Skip a specified number of bytes.
262bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
263bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param numberOfBytes The number of bytes to skip.
264bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return The number of bytes skipped or <code>-1</code>
265bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * if the end of file has been reached and
266bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * <code>throwEofException</code> is set to <code>false</code>.
267bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws EOFException if the end of file is reached and
268bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * <code>throwEofException</code> is set to <code>true</code>.
269bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws IOException if trying to read past the end of file.
270bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
271bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public long skip(long numberOfBytes) throws IOException {
272bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (eof) {
273bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            throw new IOException("Skip after end of file");
274bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
275bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (position == size) {
276bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return doEndOfFile();
277bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
278bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        position += numberOfBytes;
279bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        long returnLength = numberOfBytes;
280bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (position > size) {
281bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            returnLength = numberOfBytes - (position - size);
282bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            position = size;
283bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
284bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return returnLength;
285bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
286bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
287bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
288bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Return a byte value for the  <code>read()</code> method.
289bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * <p>
290bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * This implementation returns zero.
291bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
292bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return This implementation always returns zero.
293bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
294bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected int processByte() {
295bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // do nothing - overridable by subclass
296bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return 0;
297bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
298bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
299bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
300bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Process the bytes for the <code>read(byte[], offset, length)</code>
301bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * method.
302bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * <p>
303bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * This implementation leaves the byte array unchanged.
304bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
305bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param bytes The byte array
306bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param offset The offset to start at.
307bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param length The number of bytes.
308bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
309bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected void processBytes(byte[] bytes, int offset, int length) {
310bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // do nothing - overridable by subclass
311bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
312bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
313bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
314bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Handle End of File.
315bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
316bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return <code>-1</code> if <code>throwEofException</code> is
317bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * set to <code>false</code>
318bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @throws EOFException if <code>throwEofException</code> is set
319bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * to <code>true</code>.
320bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
321bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private int doEndOfFile() throws EOFException {
322bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        eof = true;
323bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (throwEofException) {
324bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            throw new EOFException();
325bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
326bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return -1;
327bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
328bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
329bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook}
330