ProxyCollectionWriter.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.io.output;

  18. import java.io.FilterWriter;
  19. import java.io.IOException;
  20. import java.io.Writer;
  21. import java.util.Collection;

  22. import org.apache.commons.io.IOUtils;

  23. /**
  24.  * A Proxy stream collection which acts as expected, that is it passes the method calls on to the proxied streams and
  25.  * doesn't change which methods are being called. It is an alternative base class to {@link FilterWriter} and
  26.  * {@link FilterCollectionWriter} to increase reusability, because FilterWriter changes the methods being called, such
  27.  * as {@code write(char[])} to {@code write(char[], int, int)} and {@code write(String)} to
  28.  * {@code write(String, int, int)}. This is in contrast to {@link ProxyWriter} which is backed by a single
  29.  * {@link Writer}.
  30.  *
  31.  * @since 2.7
  32.  */
  33. public class ProxyCollectionWriter extends FilterCollectionWriter {

  34.     /**
  35.      * Constructs a new proxy collection writer.
  36.      *
  37.      * @param writers Writers object to provide the underlying targets.
  38.      */
  39.     public ProxyCollectionWriter(final Collection<Writer> writers) {
  40.         super(writers);
  41.     }

  42.     /**
  43.      * Constructs a new proxy collection writer.
  44.      *
  45.      * @param writers Writers to provide the underlying targets.
  46.      */
  47.     public ProxyCollectionWriter(final Writer... writers) {
  48.         super(writers);
  49.     }

  50.     /**
  51.      * Invoked by the write methods after the proxied call has returned successfully. The number of chars written (1 for
  52.      * the {@link #write(int)} method, buffer length for {@link #write(char[])}, etc.) is given as an argument.
  53.      * <p>
  54.      * Subclasses can override this method to add common post-processing functionality without having to override all
  55.      * the write methods. The default implementation does nothing.
  56.      * </p>
  57.      *
  58.      * @param n number of chars written
  59.      * @throws IOException if the post-processing fails
  60.      */
  61.     @SuppressWarnings("unused") // Possibly thrown from subclasses.
  62.     protected void afterWrite(final int n) throws IOException {
  63.         // noop
  64.     }

  65.     /**
  66.      * Invokes the delegates' {@code append(char)} methods.
  67.      *
  68.      * @param c The character to write
  69.      * @return this writer
  70.      * @throws IOException if an I/O error occurs.
  71.      * @since 2.0
  72.      */
  73.     @Override
  74.     public Writer append(final char c) throws IOException {
  75.         try {
  76.             beforeWrite(1);
  77.             super.append(c);
  78.             afterWrite(1);
  79.         } catch (final IOException e) {
  80.             handleIOException(e);
  81.         }
  82.         return this;
  83.     }

  84.     /**
  85.      * Invokes the delegates' {@code append(CharSequence)} methods.
  86.      *
  87.      * @param csq The character sequence to write
  88.      * @return this writer
  89.      * @throws IOException if an I/O error occurs.
  90.      */
  91.     @Override
  92.     public Writer append(final CharSequence csq) throws IOException {
  93.         try {
  94.             final int len = IOUtils.length(csq);
  95.             beforeWrite(len);
  96.             super.append(csq);
  97.             afterWrite(len);
  98.         } catch (final IOException e) {
  99.             handleIOException(e);
  100.         }
  101.         return this;
  102.     }

  103.     /**
  104.      * Invokes the delegates' {@code append(CharSequence, int, int)} methods.
  105.      *
  106.      * @param csq   The character sequence to write
  107.      * @param start The index of the first character to write
  108.      * @param end   The index of the first character to write (exclusive)
  109.      * @return this writer
  110.      * @throws IOException if an I/O error occurs.
  111.      */
  112.     @Override
  113.     public Writer append(final CharSequence csq, final int start, final int end) throws IOException {
  114.         try {
  115.             beforeWrite(end - start);
  116.             super.append(csq, start, end);
  117.             afterWrite(end - start);
  118.         } catch (final IOException e) {
  119.             handleIOException(e);
  120.         }
  121.         return this;
  122.     }

  123.     /**
  124.      * Invoked by the write methods before the call is proxied. The number of chars to be written (1 for the
  125.      * {@link #write(int)} method, buffer length for {@link #write(char[])}, etc.) is given as an argument.
  126.      * <p>
  127.      * Subclasses can override this method to add common pre-processing functionality without having to override all the
  128.      * write methods. The default implementation does nothing.
  129.      * </p>
  130.      *
  131.      * @param n number of chars to be written
  132.      * @throws IOException if the pre-processing fails
  133.      */
  134.     @SuppressWarnings("unused") // Possibly thrown from subclasses.
  135.     protected void beforeWrite(final int n) throws IOException {
  136.         // noop
  137.     }

  138.     /**
  139.      * Invokes the delegate's {@code close()} method.
  140.      *
  141.      * @throws IOException if an I/O error occurs.
  142.      */
  143.     @Override
  144.     public void close() throws IOException {
  145.         try {
  146.             super.close();
  147.         } catch (final IOException e) {
  148.             handleIOException(e);
  149.         }
  150.     }

  151.     /**
  152.      * Invokes the delegate's {@code flush()} method.
  153.      *
  154.      * @throws IOException if an I/O error occurs.
  155.      */
  156.     @Override
  157.     public void flush() throws IOException {
  158.         try {
  159.             super.flush();
  160.         } catch (final IOException e) {
  161.             handleIOException(e);
  162.         }
  163.     }

  164.     /**
  165.      * Handle any IOExceptions thrown.
  166.      * <p>
  167.      * This method provides a point to implement custom exception handling. The default behavior is to re-throw the
  168.      * exception.
  169.      * </p>
  170.      *
  171.      * @param e The IOException thrown
  172.      * @throws IOException if an I/O error occurs.
  173.      */
  174.     protected void handleIOException(final IOException e) throws IOException {
  175.         throw e;
  176.     }

  177.     /**
  178.      * Invokes the delegate's {@code write(char[])} method.
  179.      *
  180.      * @param cbuf the characters to write
  181.      * @throws IOException if an I/O error occurs.
  182.      */
  183.     @Override
  184.     public void write(final char[] cbuf) throws IOException {
  185.         try {
  186.             final int len = IOUtils.length(cbuf);
  187.             beforeWrite(len);
  188.             super.write(cbuf);
  189.             afterWrite(len);
  190.         } catch (final IOException e) {
  191.             handleIOException(e);
  192.         }
  193.     }

  194.     /**
  195.      * Invokes the delegate's {@code write(char[], int, int)} method.
  196.      *
  197.      * @param cbuf the characters to write
  198.      * @param off  The start offset
  199.      * @param len  The number of characters to write
  200.      * @throws IOException if an I/O error occurs.
  201.      */
  202.     @Override
  203.     public void write(final char[] cbuf, final int off, final int len) throws IOException {
  204.         try {
  205.             beforeWrite(len);
  206.             super.write(cbuf, off, len);
  207.             afterWrite(len);
  208.         } catch (final IOException e) {
  209.             handleIOException(e);
  210.         }
  211.     }

  212.     /**
  213.      * Invokes the delegate's {@code write(int)} method.
  214.      *
  215.      * @param c the character to write
  216.      * @throws IOException if an I/O error occurs.
  217.      */
  218.     @Override
  219.     public void write(final int c) throws IOException {
  220.         try {
  221.             beforeWrite(1);
  222.             super.write(c);
  223.             afterWrite(1);
  224.         } catch (final IOException e) {
  225.             handleIOException(e);
  226.         }
  227.     }

  228.     /**
  229.      * Invokes the delegate's {@code write(String)} method.
  230.      *
  231.      * @param str the string to write
  232.      * @throws IOException if an I/O error occurs.
  233.      */
  234.     @Override
  235.     public void write(final String str) throws IOException {
  236.         try {
  237.             final int len = IOUtils.length(str);
  238.             beforeWrite(len);
  239.             super.write(str);
  240.             afterWrite(len);
  241.         } catch (final IOException e) {
  242.             handleIOException(e);
  243.         }
  244.     }

  245.     /**
  246.      * Invokes the delegate's {@code write(String)} method.
  247.      *
  248.      * @param str the string to write
  249.      * @param off The start offset
  250.      * @param len The number of characters to write
  251.      * @throws IOException if an I/O error occurs.
  252.      */
  253.     @Override
  254.     public void write(final String str, final int off, final int len) throws IOException {
  255.         try {
  256.             beforeWrite(len);
  257.             super.write(str, off, len);
  258.             afterWrite(len);
  259.         } catch (final IOException e) {
  260.             handleIOException(e);
  261.         }
  262.     }

  263. }