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