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
19 import java.io.BufferedInputStream;
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.io.OutputStream;
23
24 /**
25 * Implements a ThreadSafe version of {@link AbstractByteArrayOutputStream} using instance synchronization.
26 */
27 //@ThreadSafe
28 public class ByteArrayOutputStream extends AbstractByteArrayOutputStream {
29
30 /**
31 * Fetches entire contents of an {@link InputStream} and represent
32 * same data as result InputStream.
33 * <p>
34 * This method is useful where,
35 * </p>
36 * <ul>
37 * <li>Source InputStream is slow.</li>
38 * <li>It has network resources associated, so we cannot keep it open for
39 * long time.</li>
40 * <li>It has network timeout associated.</li>
41 * </ul>
42 * It can be used in favor of {@link #toByteArray()}, since it
43 * avoids unnecessary allocation and copy of byte[].<br>
44 * This method buffers the input internally, so there is no need to use a
45 * {@link BufferedInputStream}.
46 *
47 * @param input Stream to be fully buffered.
48 * @return A fully buffered stream.
49 * @throws IOException if an I/O error occurs.
50 * @since 2.0
51 */
52 public static InputStream toBufferedInputStream(final InputStream input)
53 throws IOException {
54 return toBufferedInputStream(input, DEFAULT_SIZE);
55 }
56
57 /**
58 * Fetches entire contents of an {@link InputStream} and represent
59 * same data as result InputStream.
60 * <p>
61 * This method is useful where,
62 * </p>
63 * <ul>
64 * <li>Source InputStream is slow.</li>
65 * <li>It has network resources associated, so we cannot keep it open for
66 * long time.</li>
67 * <li>It has network timeout associated.</li>
68 * </ul>
69 * It can be used in favor of {@link #toByteArray()}, since it
70 * avoids unnecessary allocation and copy of byte[].<br>
71 * This method buffers the input internally, so there is no need to use a
72 * {@link BufferedInputStream}.
73 *
74 * @param input Stream to be fully buffered.
75 * @param size the initial buffer size
76 * @return A fully buffered stream.
77 * @throws IOException if an I/O error occurs.
78 * @since 2.5
79 */
80 public static InputStream toBufferedInputStream(final InputStream input, final int size)
81 throws IOException {
82 try (ByteArrayOutputStream output = new ByteArrayOutputStream(size)) {
83 output.write(input);
84 return output.toInputStream();
85 }
86 }
87
88 /**
89 * Constructs a new byte array output stream. The buffer capacity is
90 * initially {@value AbstractByteArrayOutputStream#DEFAULT_SIZE} bytes, though its size increases if necessary.
91 */
92 public ByteArrayOutputStream() {
93 this(DEFAULT_SIZE);
94 }
95
96 /**
97 * Constructs a new byte array output stream, with a buffer capacity of
98 * the specified size, in bytes.
99 *
100 * @param size the initial size
101 * @throws IllegalArgumentException if size is negative
102 */
103 public ByteArrayOutputStream(final int size) {
104 if (size < 0) {
105 throw new IllegalArgumentException("Negative initial size: " + size);
106 }
107 synchronized (this) {
108 needNewBuffer(size);
109 }
110 }
111
112 /**
113 * @see java.io.ByteArrayOutputStream#reset()
114 */
115 @Override
116 public synchronized void reset() {
117 resetImpl();
118 }
119
120 @Override
121 public synchronized int size() {
122 return count;
123 }
124
125 @Override
126 public synchronized byte[] toByteArray() {
127 return toByteArrayImpl();
128 }
129
130 @Override
131 public synchronized InputStream toInputStream() {
132 return toInputStream(java.io.ByteArrayInputStream::new);
133 }
134
135 @Override
136 public void write(final byte[] b, final int off, final int len) {
137 if (off < 0
138 || off > b.length
139 || len < 0
140 || off + len > b.length
141 || off + len < 0) {
142 throw new IndexOutOfBoundsException();
143 }
144 if (len == 0) {
145 return;
146 }
147 synchronized (this) {
148 writeImpl(b, off, len);
149 }
150 }
151
152 @Override
153 public synchronized int write(final InputStream in) throws IOException {
154 return writeImpl(in);
155 }
156
157 @Override
158 public synchronized void write(final int b) {
159 writeImpl(b);
160 }
161
162 @Override
163 public synchronized void writeTo(final OutputStream out) throws IOException {
164 writeToImpl(out);
165 }
166 }