1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.fileupload.util;
18
19 import java.io.FilterInputStream;
20 import java.io.IOException;
21 import java.io.InputStream;
22
23
24 /**
25 * An input stream, which limits its data size. This stream is
26 * used, if the content length is unknown.
27 */
28 public abstract class LimitedInputStream
29 extends FilterInputStream implements Closeable {
30 /**
31 * The maximum size of an item, in bytes.
32 */
33 private long sizeMax;
34 /**
35 * The current number of bytes.
36 */
37 private long count;
38 /**
39 * Whether this stream is already closed.
40 */
41 private boolean closed;
42
43 /**
44 * Creates a new instance.
45 * @param pIn The input stream, which shall be limited.
46 * @param pSizeMax The limit; no more than this number of bytes
47 * shall be returned by the source stream.
48 */
49 public LimitedInputStream(InputStream pIn, long pSizeMax) {
50 super(pIn);
51 sizeMax = pSizeMax;
52 }
53
54 /**
55 * Called to indicate, that the input streams limit has
56 * been exceeded.
57 * @param pSizeMax The input streams limit, in bytes.
58 * @param pCount The actual number of bytes.
59 * @throws IOException The called method is expected
60 * to raise an IOException.
61 */
62 protected abstract void raiseError(long pSizeMax, long pCount)
63 throws IOException;
64
65 /** Called to check, whether the input streams
66 * limit is reached.
67 * @throws IOException The given limit is exceeded.
68 */
69 private void checkLimit() throws IOException {
70 if (count > sizeMax) {
71 raiseError(sizeMax, count);
72 }
73 }
74
75 /**
76 * Reads the next byte of data from this input stream. The value
77 * byte is returned as an <code>int</code> in the range
78 * <code>0</code> to <code>255</code>. If no byte is available
79 * because the end of the stream has been reached, the value
80 * <code>-1</code> is returned. This method blocks until input data
81 * is available, the end of the stream is detected, or an exception
82 * is thrown.
83 * <p>
84 * This method
85 * simply performs <code>in.read()</code> and returns the result.
86 *
87 * @return the next byte of data, or <code>-1</code> if the end of the
88 * stream is reached.
89 * @exception IOException if an I/O error occurs.
90 * @see java.io.FilterInputStream#in
91 */
92 public int read() throws IOException {
93 int res = super.read();
94 if (res != -1) {
95 count++;
96 checkLimit();
97 }
98 return res;
99 }
100
101 /**
102 * Reads up to <code>len</code> bytes of data from this input stream
103 * into an array of bytes. If <code>len</code> is not zero, the method
104 * blocks until some input is available; otherwise, no
105 * bytes are read and <code>0</code> is returned.
106 * <p>
107 * This method simply performs <code>in.read(b, off, len)</code>
108 * and returns the result.
109 *
110 * @param b the buffer into which the data is read.
111 * @param off The start offset in the destination array
112 * <code>b</code>.
113 * @param len the maximum number of bytes read.
114 * @return the total number of bytes read into the buffer, or
115 * <code>-1</code> if there is no more data because the end of
116 * the stream has been reached.
117 * @exception NullPointerException If <code>b</code> is <code>null</code>.
118 * @exception IndexOutOfBoundsException If <code>off</code> is negative,
119 * <code>len</code> is negative, or <code>len</code> is greater than
120 * <code>b.length - off</code>
121 * @exception IOException if an I/O error occurs.
122 * @see java.io.FilterInputStream#in
123 */
124 public int read(byte[] b, int off, int len) throws IOException {
125 int res = super.read(b, off, len);
126 if (res > 0) {
127 count += res;
128 checkLimit();
129 }
130 return res;
131 }
132
133 /**
134 * Returns, whether this stream is already closed.
135 * @return True, if the stream is closed, otherwise false.
136 * @throws IOException An I/O error occurred.
137 */
138 public boolean isClosed() throws IOException {
139 return closed;
140 }
141
142 /**
143 * Closes this input stream and releases any system resources
144 * associated with the stream.
145 * This
146 * method simply performs <code>in.close()</code>.
147 *
148 * @exception IOException if an I/O error occurs.
149 * @see java.io.FilterInputStream#in
150 */
151 public void close() throws IOException {
152 closed = true;
153 super.close();
154 }
155 }