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 }