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.output;
18
19 import java.io.FilterOutputStream;
20 import java.io.IOException;
21 import java.io.OutputStream;
22
23 /**
24 * A Proxy stream which acts as expected, that is it passes the method
25 * calls on to the proxied stream and doesn't change which methods are
26 * being called. It is an alternative base class to FilterOutputStream
27 * 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.
31 *
32 * @version $Id: ProxyOutputStream.java 1415850 2012-11-30 20:51:39Z ggregory $
33 */
34 public class ProxyOutputStream extends FilterOutputStream {
35
36 /**
37 * Constructs a new ProxyOutputStream.
38 *
39 * @param proxy the OutputStream to delegate to
40 */
41 public ProxyOutputStream(final OutputStream proxy) {
42 super(proxy);
43 // the proxy is stored in a protected superclass variable named 'out'
44 }
45
46 /**
47 * Invokes the delegate's <code>write(int)</code> method.
48 * @param idx the byte to write
49 * @throws IOException if an I/O error occurs
50 */
51 @Override
52 public void write(final int idx) throws IOException {
53 try {
54 beforeWrite(1);
55 out.write(idx);
56 afterWrite(1);
57 } catch (final IOException e) {
58 handleIOException(e);
59 }
60 }
61
62 /**
63 * Invokes the delegate's <code>write(byte[])</code> method.
64 * @param bts the bytes to write
65 * @throws IOException if an I/O error occurs
66 */
67 @Override
68 public void write(final byte[] bts) throws IOException {
69 try {
70 final int len = bts != null ? bts.length : 0;
71 beforeWrite(len);
72 out.write(bts);
73 afterWrite(len);
74 } catch (final IOException e) {
75 handleIOException(e);
76 }
77 }
78
79 /**
80 * Invokes the delegate's <code>write(byte[])</code> method.
81 * @param bts the bytes to write
82 * @param st The start offset
83 * @param end The number of bytes to write
84 * @throws IOException if an I/O error occurs
85 */
86 @Override
87 public void write(final byte[] bts, final int st, final int end) throws IOException {
88 try {
89 beforeWrite(end);
90 out.write(bts, st, end);
91 afterWrite(end);
92 } catch (final IOException e) {
93 handleIOException(e);
94 }
95 }
96
97 /**
98 * Invokes the delegate's <code>flush()</code> method.
99 * @throws IOException if an I/O error occurs
100 */
101 @Override
102 public void flush() throws IOException {
103 try {
104 out.flush();
105 } catch (final IOException e) {
106 handleIOException(e);
107 }
108 }
109
110 /**
111 * Invokes the delegate's <code>close()</code> method.
112 * @throws IOException if an I/O error occurs
113 */
114 @Override
115 public void close() throws IOException {
116 try {
117 out.close();
118 } catch (final IOException e) {
119 handleIOException(e);
120 }
121 }
122
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 2.0
133 * @param n number of bytes to be written
134 * @throws IOException if the pre-processing fails
135 */
136 protected void beforeWrite(final 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 2.0
150 * @param n number of bytes written
151 * @throws IOException if the post-processing fails
152 */
153 protected void afterWrite(final int n) throws IOException {
154 }
155
156 /**
157 * Handle any IOExceptions thrown.
158 * <p>
159 * This method provides a point to implement custom exception
160 * handling. The default behaviour is to re-throw the exception.
161 * @param e The IOException thrown
162 * @throws IOException if an I/O error occurs
163 * @since 2.0
164 */
165 protected void handleIOException(final IOException e) throws IOException {
166 throw e;
167 }
168
169 }