Skip to content

Commit 3ce24e5

Browse files
committed
IO-211: Pre- and post-processing support for proxied streams
Committed the proposed patch. git-svn-id: https://svn.apache.org/repos/asf/commons/proper/io/trunk@805151 13f79535-47bb-0310-9956-ffa450edef68
1 parent 2853baa commit 3ce24e5

5 files changed

Lines changed: 117 additions & 134 deletions

File tree

src/java/org/apache/commons/io/input/AutoCloseInputStream.java

Lines changed: 4 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -65,58 +65,16 @@ public void close() throws IOException {
6565
}
6666

6767
/**
68-
* Reads and returns a single byte from the underlying input stream.
69-
* If the underlying stream returns -1, the {@link #close()} method is
70-
* called to automatically close and discard the stream.
68+
* Automatically closes the stream if the end of stream was reached.
7169
*
72-
* @return next byte in the stream, or -1 if no more bytes are available
73-
* @throws IOException if the stream could not be read or closed
70+
* @param n number of bytes read, or -1 if no more bytes are available
71+
* @throws IOException if the stream could not be closed
7472
*/
7573
@Override
76-
public int read() throws IOException {
77-
int n = in.read();
74+
protected void afterRead(int n) throws IOException {
7875
if (n == -1) {
7976
close();
8077
}
81-
return n;
82-
}
83-
84-
/**
85-
* Reads and returns bytes from the underlying input stream to the given
86-
* buffer. If the underlying stream returns -1, the {@link #close()} method
87-
* i called to automatically close and discard the stream.
88-
*
89-
* @param b buffer to which bytes from the stream are written
90-
* @return number of bytes read, or -1 if no more bytes are available
91-
* @throws IOException if the stream could not be read or closed
92-
*/
93-
@Override
94-
public int read(byte[] b) throws IOException {
95-
int n = in.read(b);
96-
if (n == -1) {
97-
close();
98-
}
99-
return n;
100-
}
101-
102-
/**
103-
* Reads and returns bytes from the underlying input stream to the given
104-
* buffer. If the underlying stream returns -1, the {@link #close()} method
105-
* i called to automatically close and discard the stream.
106-
*
107-
* @param b buffer to which bytes from the stream are written
108-
* @param off start offset within the buffer
109-
* @param len maximum number of bytes to read
110-
* @return number of bytes read, or -1 if no more bytes are available
111-
* @throws IOException if the stream could not be read or closed
112-
*/
113-
@Override
114-
public int read(byte[] b, int off, int len) throws IOException {
115-
int n = in.read(b, off, len);
116-
if (n == -1) {
117-
close();
118-
}
119-
return n;
12078
}
12179

12280
/**

src/java/org/apache/commons/io/input/CountingInputStream.java

Lines changed: 12 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -44,54 +44,6 @@ public CountingInputStream(InputStream in) {
4444
}
4545

4646
//-----------------------------------------------------------------------
47-
/**
48-
* Reads a number of bytes into the byte array, keeping count of the
49-
* number read.
50-
*
51-
* @param b the buffer into which the data is read, not null
52-
* @return the total number of bytes read into the buffer, -1 if end of stream
53-
* @throws IOException if an I/O error occurs
54-
* @see java.io.InputStream#read(byte[])
55-
*/
56-
@Override
57-
public int read(byte[] b) throws IOException {
58-
int found = super.read(b);
59-
this.count += (found >= 0) ? found : 0;
60-
return found;
61-
}
62-
63-
/**
64-
* Reads a number of bytes into the byte array at a specific offset,
65-
* keeping count of the number read.
66-
*
67-
* @param b the buffer into which the data is read, not null
68-
* @param off the start offset in the buffer
69-
* @param len the maximum number of bytes to read
70-
* @return the total number of bytes read into the buffer, -1 if end of stream
71-
* @throws IOException if an I/O error occurs
72-
* @see java.io.InputStream#read(byte[], int, int)
73-
*/
74-
@Override
75-
public int read(byte[] b, int off, int len) throws IOException {
76-
int found = super.read(b, off, len);
77-
this.count += (found >= 0) ? found : 0;
78-
return found;
79-
}
80-
81-
/**
82-
* Reads the next byte of data adding to the count of bytes received
83-
* if a byte is successfully read.
84-
*
85-
* @return the byte read, -1 if end of stream
86-
* @throws IOException if an I/O error occurs
87-
* @see java.io.InputStream#read()
88-
*/
89-
@Override
90-
public int read() throws IOException {
91-
int found = super.read();
92-
this.count += (found >= 0) ? 1 : 0;
93-
return found;
94-
}
9547

9648
/**
9749
* Skips the stream over the specified number of bytes, adding the skipped
@@ -109,6 +61,18 @@ public long skip(final long length) throws IOException {
10961
return skip;
11062
}
11163

64+
/**
65+
* Adds the number of read bytes to the count.
66+
*
67+
* @param n number of bytes read, or -1 if no more bytes are available
68+
*/
69+
@Override
70+
protected void afterRead(int n) {
71+
if (n != -1) {
72+
this.count += n;
73+
}
74+
}
75+
11276
//-----------------------------------------------------------------------
11377
/**
11478
* The number of bytes that have passed through this stream.

src/java/org/apache/commons/io/input/ProxyInputStream.java

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@
2828
* It is an alternative base class to FilterInputStream
2929
* to increase reusability, because FilterInputStream changes the
3030
* methods being called, such as read(byte[]) to read(byte[], int, int).
31+
* <p>
32+
* See the protected methods for ways in which a subclass can easily decorate
33+
* a stream with custom pre-, post- or error processing functionality.
3134
*
3235
* @author Stephen Colebourne
3336
* @version $Id$
@@ -52,7 +55,10 @@ public ProxyInputStream(InputStream proxy) {
5255
@Override
5356
public int read() throws IOException {
5457
try {
55-
return in.read();
58+
beforeRead(1);
59+
int b = in.read();
60+
afterRead(b != -1 ? 1 : -1);
61+
return b;
5662
} catch (IOException e) {
5763
handleIOException(e);
5864
return -1;
@@ -68,7 +74,10 @@ public int read() throws IOException {
6874
@Override
6975
public int read(byte[] bts) throws IOException {
7076
try {
71-
return in.read(bts);
77+
beforeRead(bts.length);
78+
int n = in.read(bts);
79+
afterRead(n);
80+
return n;
7281
} catch (IOException e) {
7382
handleIOException(e);
7483
return -1;
@@ -86,7 +95,10 @@ public int read(byte[] bts) throws IOException {
8695
@Override
8796
public int read(byte[] bts, int off, int len) throws IOException {
8897
try {
89-
return in.read(bts, off, len);
98+
beforeRead(len);
99+
int n = in.read(bts, off, len);
100+
afterRead(n);
101+
return n;
90102
} catch (IOException e) {
91103
handleIOException(e);
92104
return -1;
@@ -168,6 +180,46 @@ public boolean markSupported() {
168180
return in.markSupported();
169181
}
170182

183+
/**
184+
* Invoked by the read methods before the call is proxied. The number
185+
* of bytes that the caller wanted to read (1 for the {@link #read()}
186+
* method, buffer length for {@link #read(byte[])}, etc.) is given as
187+
* an argument.
188+
* <p>
189+
* Subclasses can override this method to add common pre-processing
190+
* functionality without having to override all the read methods.
191+
* The default implementation does nothing.
192+
* <p>
193+
* Note this method is <em>not</em> called from {@link #skip(long)} or
194+
* {@link #reset()}. You need to explicitly override those methods if
195+
* you want to add pre-processing steps also to them.
196+
*
197+
* @since Commons IO 2.0
198+
* @param n number of bytes that the caller asked to be read
199+
* @throws IOException if the pre-processing fails
200+
*/
201+
protected void beforeRead(int n) throws IOException {
202+
}
203+
204+
/**
205+
* Invoked by the read methods after the proxied call has returned
206+
* successfully. The number of bytes returned to the caller (or -1 if
207+
* the end of stream was reached) is given as an argument.
208+
* <p>
209+
* Subclasses can override this method to add common post-processing
210+
* functionality without having to override all the read methods.
211+
* The default implementation does nothing.
212+
* <p>
213+
* Note this method is <em>not</em> called from {@link #skip(long)} or
214+
* {@link #reset()}. You need to explicitly override those methods if
215+
* you want to add post-processing steps also to them.
216+
*
217+
* @since Commons IO 2.0
218+
* @param n number of bytes read, or -1 if the end of stream was reached
219+
* @throws IOException if the post-processing fails
220+
*/
221+
protected void afterRead(int n) throws IOException {
222+
}
171223

172224
/**
173225
* Handle any IOExceptions thrown.

src/java/org/apache/commons/io/output/CountingOutputStream.java

Lines changed: 4 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -43,48 +43,15 @@ public CountingOutputStream( OutputStream out ) {
4343
}
4444

4545
//-----------------------------------------------------------------------
46-
/**
47-
* Writes the contents of the specified byte array to this output stream
48-
* keeping count of the number of bytes written.
49-
*
50-
* @param b the bytes to write, not null
51-
* @throws IOException if an I/O error occurs
52-
* @see java.io.OutputStream#write(byte[])
53-
*/
54-
@Override
55-
public void write(byte[] b) throws IOException {
56-
count += b.length;
57-
super.write(b);
58-
}
59-
60-
/**
61-
* Writes a portion of the specified byte array to this output stream
62-
* keeping count of the number of bytes written.
63-
*
64-
* @param b the bytes to write, not null
65-
* @param off the start offset in the buffer
66-
* @param len the maximum number of bytes to write
67-
* @throws IOException if an I/O error occurs
68-
* @see java.io.OutputStream#write(byte[], int, int)
69-
*/
70-
@Override
71-
public void write(byte[] b, int off, int len) throws IOException {
72-
count += len;
73-
super.write(b, off, len);
74-
}
7546

7647
/**
77-
* Writes a single byte to the output stream adding to the count of the
78-
* number of bytes written.
48+
* Updates the count with the number of bytes that are being written.
7949
*
80-
* @param b the byte to write
81-
* @throws IOException if an I/O error occurs
82-
* @see java.io.OutputStream#write(int)
50+
* @param n number of bytes to be written to the stream
8351
*/
8452
@Override
85-
public void write(int b) throws IOException {
86-
count++;
87-
super.write(b);
53+
protected void beforeWrite(int n) {
54+
count += n;
8855
}
8956

9057
//-----------------------------------------------------------------------

src/java/org/apache/commons/io/output/ProxyOutputStream.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
* calls on to the proxied stream and doesn't change which methods are
2626
* being called. It is an alternative base class to FilterOutputStream
2727
* to increase reusability.
28+
* <p>
29+
* See the protected methods for ways in which a subclass can easily decorate
30+
* a stream with custom pre-, post- or error processing functionality.
2831
*
2932
* @author Stephen Colebourne
3033
* @version $Id$
@@ -49,7 +52,9 @@ public ProxyOutputStream(OutputStream proxy) {
4952
@Override
5053
public void write(int idx) throws IOException {
5154
try {
55+
beforeWrite(1);
5256
out.write(idx);
57+
afterWrite(1);
5358
} catch (IOException e) {
5459
handleIOException(e);
5560
}
@@ -63,7 +68,9 @@ public void write(int idx) throws IOException {
6368
@Override
6469
public void write(byte[] bts) throws IOException {
6570
try {
71+
beforeWrite(bts.length);
6672
out.write(bts);
73+
afterWrite(bts.length);
6774
} catch (IOException e) {
6875
handleIOException(e);
6976
}
@@ -79,7 +86,9 @@ public void write(byte[] bts) throws IOException {
7986
@Override
8087
public void write(byte[] bts, int st, int end) throws IOException {
8188
try {
89+
beforeWrite(end);
8290
out.write(bts, st, end);
91+
afterWrite(end);
8392
} catch (IOException e) {
8493
handleIOException(e);
8594
}
@@ -111,6 +120,39 @@ public void close() throws IOException {
111120
}
112121
}
113122

123+
/**
124+
* Invoked by the write methods before the call is proxied. The number
125+
* of bytes to be written (1 for the {@link #write(int)} method, buffer
126+
* length for {@link #write(byte[])}, etc.) is given as an argument.
127+
* <p>
128+
* Subclasses can override this method to add common pre-processing
129+
* functionality without having to override all the write methods.
130+
* The default implementation does nothing.
131+
*
132+
* @since Commons IO 2.0
133+
* @param n number of bytes to be written
134+
* @throws IOException if the pre-processing fails
135+
*/
136+
protected void beforeWrite(int n) throws IOException {
137+
}
138+
139+
/**
140+
* Invoked by the write methods after the proxied call has returned
141+
* successfully. The number of bytes written (1 for the
142+
* {@link #write(int)} method, buffer length for {@link #write(byte[])},
143+
* etc.) is given as an argument.
144+
* <p>
145+
* Subclasses can override this method to add common post-processing
146+
* functionality without having to override all the write methods.
147+
* The default implementation does nothing.
148+
*
149+
* @since Commons IO 2.0
150+
* @param n number of bytes written
151+
* @throws IOException if the post-processing fails
152+
*/
153+
protected void afterWrite(int n) throws IOException {
154+
}
155+
114156
/**
115157
* Handle any IOExceptions thrown.
116158
* <p>

0 commit comments

Comments
 (0)