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.FilterOutputStream; 020 import java.io.IOException; 021 import java.io.OutputStream; 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 FilterOutputStream 027 * to increase reusability. 028 * <p> 029 * See the protected methods for ways in which a subclass can easily decorate 030 * a stream with custom pre-, post- or error processing functionality. 031 * 032 * @author Stephen Colebourne 033 * @version $Id: ProxyOutputStream.java 1003340 2010-10-01 00:31:53Z sebb $ 034 */ 035 public class ProxyOutputStream extends FilterOutputStream { 036 037 /** 038 * Constructs a new ProxyOutputStream. 039 * 040 * @param proxy the OutputStream to delegate to 041 */ 042 public ProxyOutputStream(OutputStream proxy) { 043 super(proxy); 044 // the proxy is stored in a protected superclass variable named 'out' 045 } 046 047 /** 048 * Invokes the delegate's <code>write(int)</code> method. 049 * @param idx the byte to write 050 * @throws IOException if an I/O error occurs 051 */ 052 @Override 053 public void write(int idx) throws IOException { 054 try { 055 beforeWrite(1); 056 out.write(idx); 057 afterWrite(1); 058 } catch (IOException e) { 059 handleIOException(e); 060 } 061 } 062 063 /** 064 * Invokes the delegate's <code>write(byte[])</code> method. 065 * @param bts the bytes to write 066 * @throws IOException if an I/O error occurs 067 */ 068 @Override 069 public void write(byte[] bts) throws IOException { 070 try { 071 int len = bts != null ? bts.length : 0; 072 beforeWrite(len); 073 out.write(bts); 074 afterWrite(len); 075 } catch (IOException e) { 076 handleIOException(e); 077 } 078 } 079 080 /** 081 * Invokes the delegate's <code>write(byte[])</code> method. 082 * @param bts the bytes to write 083 * @param st The start offset 084 * @param end The number of bytes to write 085 * @throws IOException if an I/O error occurs 086 */ 087 @Override 088 public void write(byte[] bts, int st, int end) throws IOException { 089 try { 090 beforeWrite(end); 091 out.write(bts, st, end); 092 afterWrite(end); 093 } catch (IOException e) { 094 handleIOException(e); 095 } 096 } 097 098 /** 099 * Invokes the delegate's <code>flush()</code> method. 100 * @throws IOException if an I/O error occurs 101 */ 102 @Override 103 public void flush() throws IOException { 104 try { 105 out.flush(); 106 } catch (IOException e) { 107 handleIOException(e); 108 } 109 } 110 111 /** 112 * Invokes the delegate's <code>close()</code> method. 113 * @throws IOException if an I/O error occurs 114 */ 115 @Override 116 public void close() throws IOException { 117 try { 118 out.close(); 119 } catch (IOException e) { 120 handleIOException(e); 121 } 122 } 123 124 /** 125 * Invoked by the write methods before the call is proxied. The number 126 * of bytes to be written (1 for the {@link #write(int)} method, buffer 127 * length for {@link #write(byte[])}, etc.) is given as an argument. 128 * <p> 129 * Subclasses can override this method to add common pre-processing 130 * functionality without having to override all the write methods. 131 * The default implementation does nothing. 132 * 133 * @since Commons IO 2.0 134 * @param n number of bytes to be written 135 * @throws IOException if the pre-processing fails 136 */ 137 protected void beforeWrite(int n) throws IOException { 138 } 139 140 /** 141 * Invoked by the write methods after the proxied call has returned 142 * successfully. The number of bytes written (1 for the 143 * {@link #write(int)} method, buffer length for {@link #write(byte[])}, 144 * etc.) is given as an argument. 145 * <p> 146 * Subclasses can override this method to add common post-processing 147 * functionality without having to override all the write methods. 148 * The default implementation does nothing. 149 * 150 * @since Commons IO 2.0 151 * @param n number of bytes written 152 * @throws IOException if the post-processing fails 153 */ 154 protected void afterWrite(int n) throws IOException { 155 } 156 157 /** 158 * Handle any IOExceptions thrown. 159 * <p> 160 * This method provides a point to implement custom exception 161 * handling. The default behaviour is to re-throw the exception. 162 * @param e The IOException thrown 163 * @throws IOException if an I/O error occurs 164 * @since Commons IO 2.0 165 */ 166 protected void handleIOException(IOException e) throws IOException { 167 throw e; 168 } 169 170 }