|
35 | 35 | import java.io.IOException; |
36 | 36 | import java.io.OutputStream; |
37 | 37 | import java.util.ArrayList; |
| 38 | +import java.util.List; |
| 39 | +import java.util.concurrent.CopyOnWriteArrayList; |
38 | 40 |
|
39 | 41 | /** |
40 | 42 | * A {@code MultiOutputStream} is a collection of constituent |
|
49 | 51 | */ |
50 | 52 | public class MultiOutputStream extends OutputStream { |
51 | 53 |
|
52 | | - private final ArrayList<OutputStream> streams; |
53 | | - |
54 | | - private OutputStream[] cachedStreams; |
| 54 | + private final List<OutputStream> streams; |
55 | 55 |
|
56 | 56 | /** |
57 | 57 | * Forwards output to a list of output streams. |
58 | 58 | * |
59 | 59 | * @param os Output streams which will receive this stream's output. |
60 | 60 | */ |
61 | 61 | public MultiOutputStream(final OutputStream... os) { |
62 | | - streams = new ArrayList<>(os.length); |
63 | | - for (int i = 0; i < os.length; i++) { |
64 | | - streams.add(os[i]); |
65 | | - } |
66 | | - cacheStreams(); |
| 62 | + streams = new CopyOnWriteArrayList<>(os); |
67 | 63 | } |
68 | 64 |
|
69 | 65 | // -- MultiOutputStream methods -- |
70 | 66 |
|
71 | 67 | /** Adds an output stream to those receiving this stream's output. */ |
72 | 68 | public void addOutputStream(final OutputStream os) { |
73 | | - synchronized (streams) { |
74 | | - streams.add(os); |
75 | | - cacheStreams(); |
76 | | - } |
| 69 | + streams.add(os); |
77 | 70 | } |
78 | 71 |
|
79 | 72 | /** Removes an output stream from those receiving this stream's output. */ |
80 | 73 | public void removeOutputStream(final OutputStream os) { |
81 | | - synchronized (streams) { |
82 | | - streams.remove(os); |
83 | | - cacheStreams(); |
84 | | - } |
| 74 | + streams.remove(os); |
85 | 75 | } |
86 | 76 |
|
87 | 77 | // -- OutputStream methods -- |
88 | 78 |
|
89 | 79 | @Override |
90 | 80 | public void write(final int b) throws IOException { |
91 | | - final OutputStream[] toWrite = cachedStreams; |
92 | | - for (final OutputStream stream : toWrite) |
| 81 | + for (final OutputStream stream : streams) |
93 | 82 | stream.write(b); |
94 | 83 | } |
95 | 84 |
|
96 | 85 | @Override |
97 | 86 | public void write(final byte[] buf, final int off, final int len) |
98 | 87 | throws IOException |
99 | 88 | { |
100 | | - final OutputStream[] toWrite = cachedStreams; |
101 | | - for (final OutputStream stream : toWrite) |
| 89 | + for (final OutputStream stream : streams) |
102 | 90 | stream.write(buf, off, len); |
103 | 91 | } |
104 | 92 |
|
105 | 93 | // -- Closeable methods -- |
106 | 94 |
|
107 | 95 | @Override |
108 | 96 | public void close() throws IOException { |
109 | | - final OutputStream[] toClose = cachedStreams; |
110 | | - for (final OutputStream stream : toClose) |
| 97 | + for (final OutputStream stream : streams) |
111 | 98 | stream.close(); |
112 | 99 | } |
113 | 100 |
|
114 | 101 | // -- Flushable methods -- |
115 | 102 |
|
116 | 103 | @Override |
117 | 104 | public void flush() throws IOException { |
118 | | - final OutputStream[] toFlush = cachedStreams; |
119 | | - for (final OutputStream stream : toFlush) |
| 105 | + for (final OutputStream stream : streams) |
120 | 106 | stream.flush(); |
121 | 107 | } |
122 | 108 |
|
123 | | - // -- Helper methods -- |
124 | | - |
125 | | - private void cacheStreams() { |
126 | | - cachedStreams = streams.toArray(new OutputStream[streams.size()]); |
127 | | - } |
128 | | - |
129 | 109 | } |
0 commit comments