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
17package com.google.common.io;
18
19import java.io.Closeable;
20import java.io.Flushable;
21import java.io.IOException;
22import java.io.Writer;
23
24/**
25 * Writer that places all output on an {@link Appendable} target. If the target
26 * is {@link Flushable} or {@link Closeable}, flush()es and close()s will also
27 * be delegated to the target.
28 *
29 * @author Alan Green
30 * @author Sebastian Kanthak
31 * @since 1.0
32 */
33class AppendableWriter extends Writer {
34  private final Appendable target;
35  private boolean closed;
36
37  /**
38   * Creates a new writer that appends everything it writes to {@code target}.
39   *
40   * @param target target to which to append output
41   */
42  AppendableWriter(Appendable target) {
43    this.target = target;
44  }
45
46  /*
47   * Abstract methods from Writer
48   */
49
50  @Override public void write(char cbuf[], int off, int len)
51      throws IOException {
52    checkNotClosed();
53    // It turns out that creating a new String is usually as fast, or faster
54    // than wrapping cbuf in a light-weight CharSequence.
55    target.append(new String(cbuf, off, len));
56  }
57
58  @Override public void flush() throws IOException {
59    checkNotClosed();
60    if (target instanceof Flushable) {
61      ((Flushable) target).flush();
62    }
63  }
64
65  @Override public void close() throws IOException {
66    this.closed = true;
67    if (target instanceof Closeable) {
68      ((Closeable) target).close();
69    }
70  }
71
72  /*
73   * Override a few functions for performance reasons to avoid creating
74   * unnecessary strings.
75   */
76
77  @Override public void write(int c) throws IOException {
78    checkNotClosed();
79    target.append((char) c);
80  }
81
82  @Override public void write(String str) throws IOException {
83    checkNotClosed();
84    target.append(str);
85  }
86
87  @Override public void write(String str, int off, int len) throws IOException {
88    checkNotClosed();
89    // tricky: append takes start, end pair...
90    target.append(str, off, off + len);
91  }
92
93  @Override public Writer append(char c) throws IOException {
94    checkNotClosed();
95    target.append(c);
96    return this;
97  }
98
99  @Override public Writer append(CharSequence charSeq) throws IOException {
100    checkNotClosed();
101    target.append(charSeq);
102    return this;
103  }
104
105  @Override public Writer append(CharSequence charSeq, int start, int end)
106      throws IOException {
107    checkNotClosed();
108    target.append(charSeq, start, end);
109    return this;
110  }
111
112  private void checkNotClosed() throws IOException {
113    if (closed) {
114      throw new IOException("Cannot write to a closed writer.");
115    }
116  }
117}
118