001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.io.output;
018
019 import java.io.FilterWriter;
020 import java.io.IOException;
021 import java.io.Writer;
022
023 /**
024 * A Proxy stream which acts as expected, that is it passes the method
025 * calls on to the proxied stream and doesn't change which methods are
026 * being called. It is an alternative base class to FilterWriter
027 * to increase reusability, because FilterWriter changes the
028 * methods being called, such as write(char[]) to write(char[], int, int)
029 * and write(String) to write(String, int, int).
030 *
031 * @version $Id: ProxyWriter.java 1304052 2012-03-22 20:55:29Z ggregory $
032 */
033 public class ProxyWriter extends FilterWriter {
034
035 /**
036 * Constructs a new ProxyWriter.
037 *
038 * @param proxy the Writer to delegate to
039 */
040 public ProxyWriter(Writer proxy) {
041 super(proxy);
042 // the proxy is stored in a protected superclass variable named 'out'
043 }
044
045 /**
046 * Invokes the delegate's <code>append(char)</code> method.
047 * @param c The character to write
048 * @return this writer
049 * @throws IOException if an I/O error occurs
050 * @since 2.0
051 */
052 @Override
053 public Writer append(char c) throws IOException {
054 try {
055 beforeWrite(1);
056 out.append(c);
057 afterWrite(1);
058 } catch (IOException e) {
059 handleIOException(e);
060 }
061 return this;
062 }
063
064 /**
065 * Invokes the delegate's <code>append(CharSequence, int, int)</code> method.
066 * @param csq The character sequence to write
067 * @param start The index of the first character to write
068 * @param end The index of the first character to write (exclusive)
069 * @return this writer
070 * @throws IOException if an I/O error occurs
071 * @since 2.0
072 */
073 @Override
074 public Writer append(CharSequence csq, int start, int end) throws IOException {
075 try {
076 beforeWrite(end - start);
077 out.append(csq, start, end);
078 afterWrite(end - start);
079 } catch (IOException e) {
080 handleIOException(e);
081 }
082 return this;
083 }
084
085 /**
086 * Invokes the delegate's <code>append(CharSequence)</code> method.
087 * @param csq The character sequence to write
088 * @return this writer
089 * @throws IOException if an I/O error occurs
090 * @since 2.0
091 */
092 @Override
093 public Writer append(CharSequence csq) throws IOException {
094 try {
095 int len = 0;
096 if (csq != null) {
097 len = csq.length();
098 }
099
100 beforeWrite(len);
101 out.append(csq);
102 afterWrite(len);
103 } catch (IOException e) {
104 handleIOException(e);
105 }
106 return this;
107 }
108
109 /**
110 * Invokes the delegate's <code>write(int)</code> method.
111 * @param idx the character to write
112 * @throws IOException if an I/O error occurs
113 */
114 @Override
115 public void write(int idx) throws IOException {
116 try {
117 beforeWrite(1);
118 out.write(idx);
119 afterWrite(1);
120 } catch (IOException e) {
121 handleIOException(e);
122 }
123 }
124
125 /**
126 * Invokes the delegate's <code>write(char[])</code> method.
127 * @param chr the characters to write
128 * @throws IOException if an I/O error occurs
129 */
130 @Override
131 public void write(char[] chr) throws IOException {
132 try {
133 int len = 0;
134 if (chr != null) {
135 len = chr.length;
136 }
137
138 beforeWrite(len);
139 out.write(chr);
140 afterWrite(len);
141 } catch (IOException e) {
142 handleIOException(e);
143 }
144 }
145
146 /**
147 * Invokes the delegate's <code>write(char[], int, int)</code> method.
148 * @param chr the characters to write
149 * @param st The start offset
150 * @param len The number of characters to write
151 * @throws IOException if an I/O error occurs
152 */
153 @Override
154 public void write(char[] chr, int st, int len) throws IOException {
155 try {
156 beforeWrite(len);
157 out.write(chr, st, len);
158 afterWrite(len);
159 } catch (IOException e) {
160 handleIOException(e);
161 }
162 }
163
164 /**
165 * Invokes the delegate's <code>write(String)</code> method.
166 * @param str the string to write
167 * @throws IOException if an I/O error occurs
168 */
169 @Override
170 public void write(String str) throws IOException {
171 try {
172 int len = 0;
173 if (str != null) {
174 len = str.length();
175 }
176
177 beforeWrite(len);
178 out.write(str);
179 afterWrite(len);
180 } catch (IOException e) {
181 handleIOException(e);
182 }
183 }
184
185 /**
186 * Invokes the delegate's <code>write(String)</code> method.
187 * @param str the string to write
188 * @param st The start offset
189 * @param len The number of characters to write
190 * @throws IOException if an I/O error occurs
191 */
192 @Override
193 public void write(String str, int st, int len) throws IOException {
194 try {
195 beforeWrite(len);
196 out.write(str, st, len);
197 afterWrite(len);
198 } catch (IOException e) {
199 handleIOException(e);
200 }
201 }
202
203 /**
204 * Invokes the delegate's <code>flush()</code> method.
205 * @throws IOException if an I/O error occurs
206 */
207 @Override
208 public void flush() throws IOException {
209 try {
210 out.flush();
211 } catch (IOException e) {
212 handleIOException(e);
213 }
214 }
215
216 /**
217 * Invokes the delegate's <code>close()</code> method.
218 * @throws IOException if an I/O error occurs
219 */
220 @Override
221 public void close() throws IOException {
222 try {
223 out.close();
224 } catch (IOException e) {
225 handleIOException(e);
226 }
227 }
228
229 /**
230 * Invoked by the write methods before the call is proxied. The number
231 * of chars to be written (1 for the {@link #write(int)} method, buffer
232 * length for {@link #write(char[])}, etc.) is given as an argument.
233 * <p>
234 * Subclasses can override this method to add common pre-processing
235 * functionality without having to override all the write methods.
236 * The default implementation does nothing.
237 *
238 * @since 2.0
239 * @param n number of chars to be written
240 * @throws IOException if the pre-processing fails
241 */
242 protected void beforeWrite(int n) throws IOException {
243 }
244
245 /**
246 * Invoked by the write methods after the proxied call has returned
247 * successfully. The number of chars written (1 for the
248 * {@link #write(int)} method, buffer length for {@link #write(char[])},
249 * etc.) is given as an argument.
250 * <p>
251 * Subclasses can override this method to add common post-processing
252 * functionality without having to override all the write methods.
253 * The default implementation does nothing.
254 *
255 * @since 2.0
256 * @param n number of chars written
257 * @throws IOException if the post-processing fails
258 */
259 protected void afterWrite(int n) throws IOException {
260 }
261
262 /**
263 * Handle any IOExceptions thrown.
264 * <p>
265 * This method provides a point to implement custom exception
266 * handling. The default behaviour is to re-throw the exception.
267 * @param e The IOException thrown
268 * @throws IOException if an I/O error occurs
269 * @since 2.0
270 */
271 protected void handleIOException(IOException e) throws IOException {
272 throw e;
273 }
274
275 }