View Javadoc
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  import org.apache.commons.io.build.AbstractOrigin;
25  import org.apache.commons.io.build.AbstractStreamBuilder;
26  import org.apache.commons.io.function.Uncheck;
27  import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;
28  
29  /**
30   * Implements a version of {@link AbstractByteArrayOutputStream} <strong>without</strong> any concurrent thread safety.
31   * <p>
32   * To build an instance, use {@link Builder}.
33   * </p>
34   *
35   * @see Builder
36   * @since 2.7
37   */
38  //@NotThreadSafe
39  public final class UnsynchronizedByteArrayOutputStream extends AbstractByteArrayOutputStream<UnsynchronizedByteArrayOutputStream> {
40  
41      // @formatter:off
42      /**
43       * Builds a new {@link UnsynchronizedByteArrayOutputStream}.
44       *
45       * <p>
46       * Using File IO:
47       * </p>
48       * <pre>{@code
49       * UnsynchronizedByteArrayOutputStream s = UnsynchronizedByteArrayOutputStream.builder()
50       *   .setBufferSize(8192)
51       *   .get();}
52       * </pre>
53       * <p>
54       * Using NIO Path:
55       * </p>
56       * <pre>{@code
57       * UnsynchronizedByteArrayOutputStream s = UnsynchronizedByteArrayOutputStream.builder()
58       *   .setBufferSize(8192)
59       *   .get();}
60       * </pre>
61       *
62       * @see #get()
63       */
64      // @formatter:on
65      public static class Builder extends AbstractStreamBuilder<UnsynchronizedByteArrayOutputStream, Builder> {
66  
67          /**
68           * Constructs a new builder of {@link UnsynchronizedByteArrayOutputStream}.
69           */
70          public Builder() {
71              // empty
72          }
73  
74          /**
75           * Builds a new {@link UnsynchronizedByteArrayOutputStream}.
76           *
77           * <p>
78           * This builder uses the following aspects:
79           * </p>
80           * <ul>
81           * <li>{@link #getBufferSize()}</li>
82           * </ul>
83           *
84           * @return a new instance.
85           * @see AbstractOrigin#getByteArray()
86           * @see #getUnchecked()
87           */
88          @Override
89          public UnsynchronizedByteArrayOutputStream get() {
90              return new UnsynchronizedByteArrayOutputStream(getBufferSize());
91          }
92  
93      }
94  
95      /**
96       * Constructs a new {@link Builder}.
97       *
98       * @return a new {@link Builder}.
99       */
100     public static Builder builder() {
101         return new Builder();
102     }
103 
104     /**
105      * Fetches entire contents of an {@link InputStream} and represent same data as result InputStream.
106      * <p>
107      * This method is useful where,
108      * </p>
109      * <ul>
110      * <li>Source InputStream is slow.</li>
111      * <li>It has network resources associated, so we cannot keep it open for long time.</li>
112      * <li>It has network timeout associated.</li>
113      * </ul>
114      * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].<br>
115      * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
116      *
117      * @param input Stream to be fully buffered.
118      * @return A fully buffered stream.
119      * @throws IOException if an I/O error occurs.
120      */
121     public static InputStream toBufferedInputStream(final InputStream input) throws IOException {
122         return toBufferedInputStream(input, DEFAULT_SIZE);
123     }
124 
125     /**
126      * Fetches entire contents of an {@link InputStream} and represent same data as result InputStream.
127      * <p>
128      * This method is useful where,
129      * </p>
130      * <ul>
131      * <li>Source InputStream is slow.</li>
132      * <li>It has network resources associated, so we cannot keep it open for long time.</li>
133      * <li>It has network timeout associated.</li>
134      * </ul>
135      * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].<br>
136      * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
137      *
138      * @param input Stream to be fully buffered.
139      * @param size the initial buffer size
140      * @return A fully buffered stream.
141      * @throws IOException if an I/O error occurs.
142      */
143     public static InputStream toBufferedInputStream(final InputStream input, final int size) throws IOException {
144         // It does not matter if a ByteArrayOutputStream is not closed as close() is a no-op
145         try (UnsynchronizedByteArrayOutputStream output = builder().setBufferSize(size).get()) {
146             output.write(input);
147             return output.toInputStream();
148         }
149     }
150 
151     /**
152      * Constructs a new byte array output stream. The buffer capacity is initially
153      *
154      * {@value AbstractByteArrayOutputStream#DEFAULT_SIZE} bytes, though its size increases if necessary.
155      * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
156      */
157     @Deprecated
158     public UnsynchronizedByteArrayOutputStream() {
159         this(DEFAULT_SIZE);
160     }
161 
162     /**
163      * Constructs a new byte array output stream, with a buffer capacity of the specified size, in bytes.
164      *
165      * @param size the initial size
166      * @throws IllegalArgumentException if size is negative
167      * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. Will be private in 3.0.0.
168      */
169     @Deprecated
170     public UnsynchronizedByteArrayOutputStream(final int size) {
171         if (size < 0) {
172             throw new IllegalArgumentException("Negative initial size: " + size);
173         }
174         needNewBuffer(size);
175     }
176 
177     /**
178      * @see java.io.ByteArrayOutputStream#reset()
179      */
180     @Override
181     public void reset() {
182         resetImpl();
183     }
184 
185     @Override
186     public int size() {
187         return count;
188     }
189 
190     @Override
191     public byte[] toByteArray() {
192         return toByteArrayImpl();
193     }
194 
195     @Override
196     public InputStream toInputStream() {
197         // @formatter:off
198         return toInputStream((buffer, offset, length) -> Uncheck
199                 .get(() -> UnsynchronizedByteArrayInputStream.builder()
200                         .setByteArray(buffer)
201                         .setOffset(offset)
202                         .setLength(length)
203                         .get()));
204         // @formatter:on
205     }
206 
207     @Override
208     public void write(final byte[] b, final int off, final int len) {
209         if (off < 0 || off > b.length || len < 0 || off + len > b.length || off + len < 0) {
210             throw new IndexOutOfBoundsException(String.format("offset=%,d, length=%,d", off, len));
211         }
212         if (len == 0) {
213             return;
214         }
215         writeImpl(b, off, len);
216     }
217 
218     @Override
219     public int write(final InputStream in) throws IOException {
220         return writeImpl(in);
221     }
222 
223     @Override
224     public void write(final int b) {
225         writeImpl(b);
226     }
227 
228     @Override
229     public void writeTo(final OutputStream out) throws IOException {
230         writeToImpl(out);
231     }
232 }