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     * @author Stephen Colebourne
032     * @version $Id: ProxyWriter.java 1003647 2010-10-01 20:53:59Z niallp $
033     */
034    public class ProxyWriter extends FilterWriter {
035    
036        /**
037         * Constructs a new ProxyWriter.
038         * 
039         * @param proxy  the Writer to delegate to
040         */
041        public ProxyWriter(Writer proxy) {
042            super(proxy);
043            // the proxy is stored in a protected superclass variable named 'out'
044        }
045    
046        /**
047         * Invokes the delegate's <code>append(char)</code> method.
048         * @param c The character to write
049         * @return this writer
050         * @throws IOException if an I/O error occurs
051         * @since Commons IO 2.0
052         */
053        @Override
054        public Writer append(char c) throws IOException {
055            try {
056                beforeWrite(1);
057                out.append(c);
058                afterWrite(1);
059            } catch (IOException e) {
060                handleIOException(e);
061            }
062            return this;
063        }
064    
065        /**
066         * Invokes the delegate's <code>append(CharSequence, int, int)</code> method.
067         * @param csq The character sequence to write
068         * @param start The index of the first character to write
069         * @param end  The index of the first character to write (exclusive)
070         * @return this writer
071         * @throws IOException if an I/O error occurs
072         * @since Commons IO 2.0
073         */
074        @Override
075        public Writer append(CharSequence csq, int start, int end) throws IOException {
076            try {
077                beforeWrite(end - start);
078                out.append(csq, start, end);
079                afterWrite(end - start);
080            } catch (IOException e) {
081                handleIOException(e);
082            }
083            return this;
084        }
085    
086        /**
087         * Invokes the delegate's <code>append(CharSequence)</code> method.
088         * @param csq The character sequence to write
089         * @return this writer
090         * @throws IOException if an I/O error occurs
091         * @since Commons IO 2.0
092         */
093        @Override
094        public Writer append(CharSequence csq) throws IOException {
095            try {
096                int len = 0;
097                if (csq != null) {
098                    len = csq.length();
099                }
100    
101                beforeWrite(len);
102                out.append(csq);
103                afterWrite(len);
104            } catch (IOException e) {
105                handleIOException(e);
106            }
107            return this;
108        }
109    
110        /**
111         * Invokes the delegate's <code>write(int)</code> method.
112         * @param idx the character to write
113         * @throws IOException if an I/O error occurs
114         */
115        @Override
116        public void write(int idx) throws IOException {
117            try {
118                beforeWrite(1);
119                out.write(idx);
120                afterWrite(1);
121            } catch (IOException e) {
122                handleIOException(e);
123            }
124        }
125    
126        /**
127         * Invokes the delegate's <code>write(char[])</code> method.
128         * @param chr the characters to write
129         * @throws IOException if an I/O error occurs
130         */
131        @Override
132        public void write(char[] chr) throws IOException {
133            try {
134                int len = 0;
135                if (chr != null) {
136                    len = chr.length;
137                }
138    
139                beforeWrite(len);
140                out.write(chr);
141                afterWrite(len);
142            } catch (IOException e) {
143                handleIOException(e);
144            }
145        }
146    
147        /**
148         * Invokes the delegate's <code>write(char[], int, int)</code> method.
149         * @param chr the characters to write
150         * @param st The start offset
151         * @param len The number of characters to write
152         * @throws IOException if an I/O error occurs
153         */
154        @Override
155        public void write(char[] chr, int st, int len) throws IOException {
156            try {
157                beforeWrite(len);
158                out.write(chr, st, len);
159                afterWrite(len);
160            } catch (IOException e) {
161                handleIOException(e);
162            }
163        }
164    
165        /**
166         * Invokes the delegate's <code>write(String)</code> method.
167         * @param str the string to write
168         * @throws IOException if an I/O error occurs
169         */
170        @Override
171        public void write(String str) throws IOException {
172            try {
173                int len = 0;
174                if (str != null) {
175                    len = str.length();
176                }
177    
178                beforeWrite(len);
179                out.write(str);
180                afterWrite(len);
181            } catch (IOException e) {
182                handleIOException(e);
183            }
184        }
185    
186        /**
187         * Invokes the delegate's <code>write(String)</code> method.
188         * @param str the string to write
189         * @param st The start offset
190         * @param len The number of characters to write
191         * @throws IOException if an I/O error occurs
192         */
193        @Override
194        public void write(String str, int st, int len) throws IOException {
195            try {
196                beforeWrite(len);
197                out.write(str, st, len);
198                afterWrite(len);
199            } catch (IOException e) {
200                handleIOException(e);
201            }
202        }
203    
204        /**
205         * Invokes the delegate's <code>flush()</code> method.
206         * @throws IOException if an I/O error occurs
207         */
208        @Override
209        public void flush() throws IOException {
210            try {
211                out.flush();
212            } catch (IOException e) {
213                handleIOException(e);
214            }
215        }
216    
217        /**
218         * Invokes the delegate's <code>close()</code> method.
219         * @throws IOException if an I/O error occurs
220         */
221        @Override
222        public void close() throws IOException {
223            try {
224                out.close();
225            } catch (IOException e) {
226                handleIOException(e);
227            }
228        }
229    
230        /**
231         * Invoked by the write methods before the call is proxied. The number
232         * of chars to be written (1 for the {@link #write(int)} method, buffer
233         * length for {@link #write(char[])}, etc.) is given as an argument.
234         * <p>
235         * Subclasses can override this method to add common pre-processing
236         * functionality without having to override all the write methods.
237         * The default implementation does nothing.
238         *
239         * @since Commons IO 2.0
240         * @param n number of chars to be written
241         * @throws IOException if the pre-processing fails
242         */
243        protected void beforeWrite(int n) throws IOException {
244        }
245    
246        /**
247         * Invoked by the write methods after the proxied call has returned
248         * successfully. The number of chars written (1 for the
249         * {@link #write(int)} method, buffer length for {@link #write(char[])},
250         * etc.) is given as an argument.
251         * <p>
252         * Subclasses can override this method to add common post-processing
253         * functionality without having to override all the write methods.
254         * The default implementation does nothing.
255         *
256         * @since Commons IO 2.0
257         * @param n number of chars written
258         * @throws IOException if the post-processing fails
259         */
260        protected void afterWrite(int n) throws IOException {
261        }
262    
263        /**
264         * Handle any IOExceptions thrown.
265         * <p>
266         * This method provides a point to implement custom exception
267         * handling. The default behaviour is to re-throw the exception.
268         * @param e The IOException thrown
269         * @throws IOException if an I/O error occurs
270         * @since Commons IO 2.0
271         */
272        protected void handleIOException(IOException e) throws IOException {
273            throw e;
274        }
275    
276    }