Home | History | Annotate | Download | only in io
      1 /*
      2  * Copyright (C) 2006 The Guava Authors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.common.io;
     18 
     19 import static com.google.common.base.Preconditions.checkNotNull;
     20 
     21 import java.io.Closeable;
     22 import java.io.Flushable;
     23 import java.io.IOException;
     24 import java.io.Writer;
     25 
     26 import javax.annotation.Nullable;
     27 
     28 /**
     29  * Writer that places all output on an {@link Appendable} target. If the target
     30  * is {@link Flushable} or {@link Closeable}, flush()es and close()s will also
     31  * be delegated to the target.
     32  *
     33  * @author Alan Green
     34  * @author Sebastian Kanthak
     35  * @since 1.0
     36  */
     37 class AppendableWriter extends Writer {
     38   private final Appendable target;
     39   private boolean closed;
     40 
     41   /**
     42    * Creates a new writer that appends everything it writes to {@code target}.
     43    *
     44    * @param target target to which to append output
     45    */
     46   AppendableWriter(Appendable target) {
     47     this.target = checkNotNull(target);
     48   }
     49 
     50   /*
     51    * Abstract methods from Writer
     52    */
     53 
     54   @Override public void write(char cbuf[], int off, int len)
     55       throws IOException {
     56     checkNotClosed();
     57     // It turns out that creating a new String is usually as fast, or faster
     58     // than wrapping cbuf in a light-weight CharSequence.
     59     target.append(new String(cbuf, off, len));
     60   }
     61 
     62   @Override public void flush() throws IOException {
     63     checkNotClosed();
     64     if (target instanceof Flushable) {
     65       ((Flushable) target).flush();
     66     }
     67   }
     68 
     69   @Override public void close() throws IOException {
     70     this.closed = true;
     71     if (target instanceof Closeable) {
     72       ((Closeable) target).close();
     73     }
     74   }
     75 
     76   /*
     77    * Override a few functions for performance reasons to avoid creating
     78    * unnecessary strings.
     79    */
     80 
     81   @Override public void write(int c) throws IOException {
     82     checkNotClosed();
     83     target.append((char) c);
     84   }
     85 
     86   @Override public void write(@Nullable String str) throws IOException {
     87     checkNotClosed();
     88     target.append(str);
     89   }
     90 
     91   @Override public void write(@Nullable String str, int off, int len) throws IOException {
     92     checkNotClosed();
     93     // tricky: append takes start, end pair...
     94     target.append(str, off, off + len);
     95   }
     96 
     97   @Override public Writer append(char c) throws IOException {
     98     checkNotClosed();
     99     target.append(c);
    100     return this;
    101   }
    102 
    103   @Override public Writer append(@Nullable CharSequence charSeq) throws IOException {
    104     checkNotClosed();
    105     target.append(charSeq);
    106     return this;
    107   }
    108 
    109   @Override public Writer append(@Nullable CharSequence charSeq, int start, int end)
    110       throws IOException {
    111     checkNotClosed();
    112     target.append(charSeq, start, end);
    113     return this;
    114   }
    115 
    116   private void checkNotClosed() throws IOException {
    117     if (closed) {
    118       throw new IOException("Cannot write to a closed writer.");
    119     }
    120   }
    121 }
    122