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