Skip to content

Commit c88a865

Browse files
author
Niall Pemberton
committed
IO-197 Copy BoundedInputStream from Apache JackRabbit
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/io/trunk@1002430 13f79535-47bb-0310-9956-ffa450edef68
1 parent 4286199 commit c88a865

1 file changed

Lines changed: 183 additions & 0 deletions

File tree

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.commons.io.input;
18+
19+
import java.io.IOException;
20+
import java.io.InputStream;
21+
22+
/**
23+
* This is a stream that will only supply bytes up to a certain length - if its
24+
* position goes above that, it will stop.
25+
* <p>
26+
* This is useful to wrap ServletInputStreams. The ServletInputStream will block
27+
* if you try to read content from it that isn't there, because it doesn't know
28+
* whether the content hasn't arrived yet or whether the content has finished.
29+
* So, one of these, initialized with the Content-length sent in the
30+
* ServletInputStream's header, will stop it blocking, providing it's been sent
31+
* with a correct content length.
32+
*
33+
* @author InigoSurguy
34+
*/
35+
public class BoundedInputStream extends InputStream {
36+
37+
/** the wrapped input stream */
38+
private final InputStream in;
39+
40+
/** the max length to provide */
41+
private final int max;
42+
43+
/** the number of bytes already returned */
44+
private int pos = 0;
45+
46+
/** the marked position */
47+
private int mark = -1;
48+
49+
/** flag if close shoud be propagated */
50+
private boolean propagateClose = true;
51+
52+
/**
53+
* Creates a new <code>BoundedInputStream</code> that wraps the given input
54+
* stream and limits it to a certain size.
55+
*
56+
* @param in The wrapped input stream
57+
* @param size The maximum number of bytes to return
58+
*/
59+
public BoundedInputStream(InputStream in, long size) {
60+
// Some badly designed methods - eg the servlet API - overload length
61+
// such that "-1" means stream finished
62+
this.max = (int) size;
63+
this.in = in;
64+
}
65+
66+
public BoundedInputStream(InputStream in) {
67+
this(in, -1);
68+
}
69+
70+
/**
71+
* {@inheritDoc}
72+
*/
73+
@Override
74+
public int read() throws IOException {
75+
if (max>=0 && pos==max) {
76+
return -1;
77+
}
78+
int result = in.read();
79+
pos++;
80+
return result;
81+
}
82+
83+
/**
84+
* {@inheritDoc}
85+
*/
86+
@Override
87+
public int read(byte[] b) throws IOException {
88+
return this.read(b, 0, b.length);
89+
}
90+
91+
/**
92+
* {@inheritDoc}
93+
*/
94+
@Override
95+
public int read(byte[] b, int off, int len) throws IOException {
96+
if (max>=0 && pos>=max) {
97+
return -1;
98+
}
99+
int maxRead = max>=0 ? Math.min(len, max-pos) : len;
100+
int bytesRead = in.read(b, off, maxRead);
101+
102+
if (bytesRead==-1) {
103+
return -1;
104+
}
105+
106+
pos+=bytesRead;
107+
return bytesRead;
108+
}
109+
110+
/**
111+
* {@inheritDoc}
112+
*/
113+
@Override
114+
public long skip(long n) throws IOException {
115+
long toSkip = max>=0 ? Math.min(n, max-pos) : n;
116+
long skippedBytes = in.skip(toSkip);
117+
pos+=skippedBytes;
118+
return skippedBytes;
119+
}
120+
121+
/**
122+
* {@inheritDoc}
123+
*/
124+
@Override
125+
public int available() throws IOException {
126+
if (max>=0 && pos>=max) {
127+
return 0;
128+
}
129+
return in.available();
130+
}
131+
132+
/**
133+
* {@inheritDoc}
134+
*/
135+
@Override
136+
public String toString() {
137+
return in.toString();
138+
}
139+
140+
/**
141+
* {@inheritDoc}
142+
*/
143+
@Override
144+
public void close() throws IOException {
145+
if (propagateClose) {
146+
in.close();
147+
}
148+
}
149+
150+
/**
151+
* {@inheritDoc}
152+
*/
153+
@Override
154+
public synchronized void reset() throws IOException {
155+
in.reset();
156+
pos = mark;
157+
}
158+
159+
/**
160+
* {@inheritDoc}
161+
*/
162+
@Override
163+
public synchronized void mark(int readlimit) {
164+
in.mark(readlimit);
165+
mark = pos;
166+
}
167+
168+
/**
169+
* {@inheritDoc}
170+
*/
171+
@Override
172+
public boolean markSupported() {
173+
return in.markSupported();
174+
}
175+
176+
public boolean isPropagateClose() {
177+
return propagateClose;
178+
}
179+
180+
public void setPropagateClose(boolean propagateClose) {
181+
this.propagateClose = propagateClose;
182+
}
183+
}

0 commit comments

Comments
 (0)