284d53dd25233bd8a9ea1dbbb2ec5fcc0065f2a5
[jSite2.git] / src / net / pterodactylus / util / io / LimitedInputStream.java
1 /**
2  * © 2008 INA Service GmbH
3  */
4 package net.pterodactylus.util.io;
5
6 import java.io.FilterInputStream;
7 import java.io.IOException;
8 import java.io.InputStream;
9
10 /**
11  * A wrapper around an {@link InputStream} that only supplies a limit number of
12  * bytes from the underlying input stream.
13  * 
14  * @author <a href="mailto:dr@ina-germany.de">David Roden</a>
15  * @version $Id$
16  */
17 public class LimitedInputStream extends FilterInputStream {
18
19         /** The remaining number of bytes that can be read. */
20         private long remaining;
21
22         /**
23          * Creates a new LimitedInputStream that supplies at most
24          * <code>length</code> bytes from the given input stream.
25          * 
26          * @param inputStream
27          *            The input stream
28          * @param length
29          *            The number of bytes to read
30          */
31         public LimitedInputStream(InputStream inputStream, long length) {
32                 super(inputStream);
33                 remaining = length;
34         }
35
36         /**
37          * @see java.io.FilterInputStream#available()
38          */
39         @Override
40         public synchronized int available() throws IOException {
41                 if (remaining == 0) {
42                         return 0;
43                 }
44                 return (int) Math.min(super.available(), Math.min(Integer.MAX_VALUE, remaining));
45         }
46
47         /**
48          * @see java.io.FilterInputStream#read()
49          */
50         @Override
51         public synchronized int read() throws IOException {
52                 int read = -1;
53                 if (remaining > 0) {
54                         read = super.read();
55                         remaining--;
56                 }
57                 return read;
58         }
59
60         /**
61          * @see java.io.FilterInputStream#read(byte[], int, int)
62          */
63         @Override
64         public synchronized int read(byte[] b, int off, int len) throws IOException {
65                 if (remaining == 0) {
66                         return -1;
67                 }
68                 int toCopy = (int) Math.min(len, Math.min(remaining, Integer.MAX_VALUE));
69                 int read = super.read(b, off, toCopy);
70                 remaining -= read;
71                 return read;
72         }
73
74         /**
75          * @see java.io.FilterInputStream#skip(long)
76          */
77         @Override
78         public synchronized long skip(long n) throws IOException {
79                 if ((n < 0)  || (remaining == 0)) {
80                         return 0;
81                 }
82                 long skipped = super.skip(Math.min(n, remaining));
83                 remaining -= skipped;
84                 return skipped;
85         }
86
87         /**
88          * {@inheritDoc}
89          * 
90          * This method does nothing, as {@link #mark(int)} and {@link #reset()} are
91          * not supported.
92          * 
93          * @see java.io.FilterInputStream#mark(int)
94          */
95         @Override
96         public void mark(int readlimit) {
97                 /* do nothing. */
98         }
99
100         /**
101          * {@inheritDoc}
102          * 
103          * @see java.io.FilterInputStream#markSupported()
104          * @return <code>false</code>
105          */
106         @Override
107         public boolean markSupported() {
108                 return false;
109         }
110
111         /**
112          * {@inheritDoc}
113          * 
114          * This method does nothing, as {@link #mark(int)} and {@link #reset()} are
115          * not supported.
116          * 
117          * @see java.io.FilterInputStream#reset()
118          */
119         @Override
120         public void reset() throws IOException {
121                 /* do nothing. */
122         }
123
124         /**
125          * Consumes the input stream, i.e. read all bytes until the limit is
126          * reached.
127          * 
128          * @throws IOException
129          *             if an I/O error occurs
130          */
131         public void consume() throws IOException {
132                 while (remaining > 0) {
133                         skip(remaining);
134                 }
135         }
136
137 }