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 }