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