001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.io.output; 018 019import java.io.BufferedInputStream; 020import java.io.IOException; 021import java.io.InputStream; 022import java.io.OutputStream; 023 024/** 025 * Implements a ThreadSafe version of {@link AbstractByteArrayOutputStream} using instance synchronization. 026 */ 027//@ThreadSafe 028public class ByteArrayOutputStream extends AbstractByteArrayOutputStream { 029 030 /** 031 * Fetches entire contents of an {@link InputStream} and represent 032 * same data as result InputStream. 033 * <p> 034 * This method is useful where, 035 * </p> 036 * <ul> 037 * <li>Source InputStream is slow.</li> 038 * <li>It has network resources associated, so we cannot keep it open for 039 * long time.</li> 040 * <li>It has network timeout associated.</li> 041 * </ul> 042 * It can be used in favor of {@link #toByteArray()}, since it 043 * avoids unnecessary allocation and copy of byte[].<br> 044 * This method buffers the input internally, so there is no need to use a 045 * {@link BufferedInputStream}. 046 * 047 * @param input Stream to be fully buffered. 048 * @return A fully buffered stream. 049 * @throws IOException if an I/O error occurs. 050 * @since 2.0 051 */ 052 public static InputStream toBufferedInputStream(final InputStream input) 053 throws IOException { 054 return toBufferedInputStream(input, DEFAULT_SIZE); 055 } 056 057 /** 058 * Fetches entire contents of an {@link InputStream} and represent 059 * same data as result InputStream. 060 * <p> 061 * This method is useful where, 062 * </p> 063 * <ul> 064 * <li>Source InputStream is slow.</li> 065 * <li>It has network resources associated, so we cannot keep it open for 066 * long time.</li> 067 * <li>It has network timeout associated.</li> 068 * </ul> 069 * It can be used in favor of {@link #toByteArray()}, since it 070 * avoids unnecessary allocation and copy of byte[].<br> 071 * This method buffers the input internally, so there is no need to use a 072 * {@link BufferedInputStream}. 073 * 074 * @param input Stream to be fully buffered. 075 * @param size the initial buffer size 076 * @return A fully buffered stream. 077 * @throws IOException if an I/O error occurs. 078 * @since 2.5 079 */ 080 public static InputStream toBufferedInputStream(final InputStream input, final int size) 081 throws IOException { 082 try (ByteArrayOutputStream output = new ByteArrayOutputStream(size)) { 083 output.write(input); 084 return output.toInputStream(); 085 } 086 } 087 088 /** 089 * Constructs a new byte array output stream. The buffer capacity is 090 * initially {@value AbstractByteArrayOutputStream#DEFAULT_SIZE} bytes, though its size increases if necessary. 091 */ 092 public ByteArrayOutputStream() { 093 this(DEFAULT_SIZE); 094 } 095 096 /** 097 * Constructs a new byte array output stream, with a buffer capacity of 098 * the specified size, in bytes. 099 * 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}