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