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.IOException; 020import java.io.InputStream; 021import java.io.OutputStream; 022 023/** 024 * Implements a ThreadSafe version of {@link AbstractByteArrayOutputStream} using instance synchronization. 025 */ 026//@ThreadSafe 027public class ByteArrayOutputStream extends AbstractByteArrayOutputStream { 028 029 /** 030 * Creates a new byte array output stream. The buffer capacity is 031 * initially {@value AbstractByteArrayOutputStream#DEFAULT_SIZE} bytes, though its size increases if necessary. 032 */ 033 public ByteArrayOutputStream() { 034 this(DEFAULT_SIZE); 035 } 036 037 /** 038 * Creates a new byte array output stream, with a buffer capacity of 039 * the specified size, in bytes. 040 * 041 * @param size the initial size 042 * @throws IllegalArgumentException if size is negative 043 */ 044 public ByteArrayOutputStream(final int size) { 045 if (size < 0) { 046 throw new IllegalArgumentException( 047 "Negative initial size: " + size); 048 } 049 synchronized (this) { 050 needNewBuffer(size); 051 } 052 } 053 054 @Override 055 public void write(final byte[] b, final int off, final int len) { 056 if ((off < 0) 057 || (off > b.length) 058 || (len < 0) 059 || ((off + len) > b.length) 060 || ((off + len) < 0)) { 061 throw new IndexOutOfBoundsException(); 062 } else if (len == 0) { 063 return; 064 } 065 synchronized (this) { 066 writeImpl(b, off, len); 067 } 068 } 069 070 @Override 071 public synchronized void write(final int b) { 072 writeImpl(b); 073 } 074 075 @Override 076 public synchronized int write(final InputStream in) throws IOException { 077 return writeImpl(in); 078 } 079 080 @Override 081 public synchronized int size() { 082 return count; 083 } 084 085 /** 086 * @see java.io.ByteArrayOutputStream#reset() 087 */ 088 @Override 089 public synchronized void reset() { 090 resetImpl(); 091 } 092 093 @Override 094 public synchronized void writeTo(final OutputStream out) throws IOException { 095 writeToImpl(out); 096 } 097 098 /** 099 * Fetches entire contents of an <code>InputStream</code> and represent 100 * same data as result InputStream. 101 * <p> 102 * This method is useful where, 103 * </p> 104 * <ul> 105 * <li>Source InputStream is slow.</li> 106 * <li>It has network resources associated, so we cannot keep it open for 107 * long time.</li> 108 * <li>It has network timeout associated.</li> 109 * </ul> 110 * It can be used in favor of {@link #toByteArray()}, since it 111 * avoids unnecessary allocation and copy of byte[].<br> 112 * This method buffers the input internally, so there is no need to use a 113 * <code>BufferedInputStream</code>. 114 * 115 * @param input Stream to be fully buffered. 116 * @return A fully buffered stream. 117 * @throws IOException if an I/O error occurs 118 * @since 2.0 119 */ 120 public static InputStream toBufferedInputStream(final InputStream input) 121 throws IOException { 122 return toBufferedInputStream(input, DEFAULT_SIZE); 123 } 124 125 /** 126 * Fetches entire contents of an <code>InputStream</code> and represent 127 * same data as result InputStream. 128 * <p> 129 * This method is useful where, 130 * </p> 131 * <ul> 132 * <li>Source InputStream is slow.</li> 133 * <li>It has network resources associated, so we cannot keep it open for 134 * long time.</li> 135 * <li>It has network timeout associated.</li> 136 * </ul> 137 * It can be used in favor of {@link #toByteArray()}, since it 138 * avoids unnecessary allocation and copy of byte[].<br> 139 * This method buffers the input internally, so there is no need to use a 140 * <code>BufferedInputStream</code>. 141 * 142 * @param input Stream to be fully buffered. 143 * @param size the initial buffer size 144 * @return A fully buffered stream. 145 * @throws IOException if an I/O error occurs 146 * @since 2.5 147 */ 148 public static InputStream toBufferedInputStream(final InputStream input, final int size) 149 throws IOException { 150 try (final ByteArrayOutputStream output = new ByteArrayOutputStream(size)) { 151 output.write(input); 152 return output.toInputStream(); 153 } 154 } 155 156 @Override 157 public synchronized InputStream toInputStream() { 158 return toInputStream(java.io.ByteArrayInputStream::new); 159 } 160 161 @Override 162 public synchronized byte[] toByteArray() { 163 return toByteArrayImpl(); 164 } 165}