2
* Copyright 2005-2012 Restlet S.A.S.
4
* The contents of this file are subject to the terms of one of the following
5
* open source licenses: Apache 2.0 or LGPL 3.0 or LGPL 2.1 or CDDL 1.0 or EPL
6
* 1.0 (the "Licenses"). You can select the license that you prefer but you may
7
* not use this file except in compliance with one of these Licenses.
9
* You can obtain a copy of the Apache 2.0 license at
10
* http://www.opensource.org/licenses/apache-2.0
12
* You can obtain a copy of the LGPL 3.0 license at
13
* http://www.opensource.org/licenses/lgpl-3.0
15
* You can obtain a copy of the LGPL 2.1 license at
16
* http://www.opensource.org/licenses/lgpl-2.1
18
* You can obtain a copy of the CDDL 1.0 license at
19
* http://www.opensource.org/licenses/cddl1
21
* You can obtain a copy of the EPL 1.0 license at
22
* http://www.opensource.org/licenses/eclipse-1.0
24
* See the Licenses for the specific language governing permissions and
25
* limitations under the Licenses.
27
* Alternatively, you can obtain a royalty free commercial license with less
28
* limitations, transferable or non-transferable, directly at
29
* http://www.restlet.com/products/restlet-framework
31
* Restlet is a registered trademark of Restlet S.A.S.
34
package org.restlet.engine.http.io;
36
import java.io.IOException;
37
import java.io.InputStream;
41
* Input stream based on a source stream that must only be partially read.
43
* @author Jerome Louvel
45
public class SizedInputStream extends InputEntityStream {
47
/** The total size that should be read from the source stream. */
48
private volatile long availableSize;
50
/** The total size when the {@link #mark(int)} method was called. */
51
private volatile long markedAvailableSize;
57
* The notifiable connection.
58
* @param inboundStream
61
* The total size that should be read from the source stream.
63
public SizedInputStream(Notifiable notifiable, InputStream inboundStream,
65
super(notifiable, inboundStream);
66
this.availableSize = size;
67
this.markedAvailableSize = -1;
71
public int available() throws IOException {
72
return Math.min((int) this.availableSize, getInboundStream()
77
public void close() throws IOException {
78
// Don't close it directly
82
public synchronized void mark(int readlimit) {
83
if (markSupported()) {
84
this.markedAvailableSize = availableSize;
87
getInboundStream().mark(readlimit);
91
public boolean markSupported() {
92
return getInboundStream().markSupported();
96
* Reads a byte from the underlying stream.
98
* @return The byte read, or -1 if the end of the stream has been reached.
101
public int read() throws IOException {
104
if (this.availableSize > 0) {
105
result = getInboundStream().read();
108
this.availableSize--;
114
// The stream has been fully read.
115
if (this.availableSize <= 0) {
123
public int read(byte b[], int off, int len) throws IOException {
126
if (this.availableSize > 0) {
127
result = getInboundStream().read(b, off,
128
Math.min(len, (int) this.availableSize));
131
this.availableSize -= result;
132
} else if (result == -1) {
137
if (this.availableSize <= 0) {
145
public synchronized void reset() throws IOException {
146
if (markSupported()) {
147
if (this.markedAvailableSize != -1) {
148
this.availableSize = markedAvailableSize;
149
this.markedAvailableSize = -1;
153
getInboundStream().reset();
157
public long skip(long n) throws IOException {
158
return getInboundStream().skip(n);