/* * Copyright 2001-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.axis.utils; import org.apache.axis.AxisEngine; import org.apache.axis.AxisProperties; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * Class ByteArray */ public class ByteArray extends OutputStream { protected static double DEFAULT_CACHE_INCREMENT = 2.5; protected static int DEFAULT_RESIDENT_SIZE = 512 * 1024 * 1024; // 512 MB protected static boolean DEFAULT_ENABLE_BACKING_STORE = true; protected static int WORKING_BUFFER_SIZE = 8192; protected org.apache.axis.utils.ByteArrayOutputStream cache = null; protected int max_size = 0; protected File bs_handle = null; protected OutputStream bs_stream = null; protected long count = 0; protected boolean enableBackingStore = DEFAULT_ENABLE_BACKING_STORE; public boolean isEnableBackingStore() { return enableBackingStore; } public void setEnableBackingStore(boolean enableBackingStore) { this.enableBackingStore = enableBackingStore; } public static boolean isDEFAULT_ENABLE_BACKING_STORE() { return DEFAULT_ENABLE_BACKING_STORE; } public static void setDEFAULT_ENABLE_BACKING_STORE( boolean DEFAULT_ENABLE_BACKING_STORE) { ByteArray.DEFAULT_ENABLE_BACKING_STORE = DEFAULT_ENABLE_BACKING_STORE; } public static int getDEFAULT_RESIDENT_SIZE() { return DEFAULT_RESIDENT_SIZE; } public static void setDEFAULT_RESIDENT_SIZE(int DEFAULT_RESIDENT_SIZE) { ByteArray.DEFAULT_RESIDENT_SIZE = DEFAULT_RESIDENT_SIZE; } public static double getDEFAULT_CACHE_INCREMENT() { return DEFAULT_CACHE_INCREMENT; } public static void setDEFAULT_CACHE_INCREMENT( double DEFAULT_CACHE_INCREMENT) { ByteArray.DEFAULT_CACHE_INCREMENT = DEFAULT_CACHE_INCREMENT; } static { String value; value = AxisProperties.getProperty( AxisEngine.PROP_BYTE_BUFFER_CACHE_INCREMENT, "" + DEFAULT_CACHE_INCREMENT); DEFAULT_CACHE_INCREMENT = Double.parseDouble(value); value = AxisProperties.getProperty( AxisEngine.PROP_BYTE_BUFFER_RESIDENT_MAX_SIZE, "" + DEFAULT_RESIDENT_SIZE); DEFAULT_RESIDENT_SIZE = Integer.parseInt(value); value = AxisProperties.getProperty( AxisEngine.PROP_BYTE_BUFFER_WORK_BUFFER_SIZE, "" + WORKING_BUFFER_SIZE); WORKING_BUFFER_SIZE = Integer.parseInt(value); value = AxisProperties.getProperty(AxisEngine.PROP_BYTE_BUFFER_BACKING, "" + DEFAULT_ENABLE_BACKING_STORE); if (value.equalsIgnoreCase("true") || value.equals("1") || value.equalsIgnoreCase("yes")) { DEFAULT_ENABLE_BACKING_STORE = true; } else { DEFAULT_ENABLE_BACKING_STORE = false; } } /** * Constructor ByteArray */ public ByteArray() { this(DEFAULT_RESIDENT_SIZE); } /** * Constructor ByteArray * * @param max_resident_size */ public ByteArray(int max_resident_size) { this(0, max_resident_size); } /** * Constructor ByteArray * * @param probable_size * @param max_resident_size */ public ByteArray(int probable_size, int max_resident_size) { if (probable_size > max_resident_size) { probable_size = 0; } if (probable_size < WORKING_BUFFER_SIZE) { probable_size = WORKING_BUFFER_SIZE; } cache = new org.apache.axis.utils.ByteArrayOutputStream(probable_size); max_size = max_resident_size; } /** * Method write * * @param bytes * @throws IOException */ public void write(byte bytes[]) throws IOException { write(bytes, 0, bytes.length); } /** * Method write * * @param bytes * @param start * @param length * @throws IOException */ public void write(byte bytes[], int start, int length) throws IOException { count += length; if (cache != null) { increaseCapacity(length); } if (cache != null) { cache.write(bytes, start, length); } else if (bs_stream != null) { bs_stream.write(bytes, start, length); } else { throw new IOException("ByteArray does not have a backing store!"); } } /** * Method write * * @param b * @throws IOException */ public void write(int b) throws IOException { count += 1; if (cache != null) { increaseCapacity(1); } if (cache != null) { cache.write(b); } else if (bs_stream != null) { bs_stream.write(b); } else { throw new IOException("ByteArray does not have a backing store!"); } } /** * Method close * * @throws IOException */ public void close() throws IOException { if (bs_stream != null) { bs_stream.close(); bs_stream = null; } } /** * Method size * * @return */ public long size() { return count; } /** * Method flush * * @throws IOException */ public void flush() throws IOException { if (bs_stream != null) { bs_stream.flush(); } } /** * Method increaseCapacity * * @param count * @throws IOException */ protected void increaseCapacity(int count) throws IOException { if (cache == null) { return; } if (count + cache.size() <= max_size) { return; } else if (enableBackingStore) { switchToBackingStore(); } else { throw new IOException("ByteArray can not increase capacity by " + count + " due to max size limit of " + max_size); } } /** * Method discardBuffer */ public synchronized void discardBuffer() { cache = null; if (bs_stream != null) { try { bs_stream.close(); } catch (IOException e) { // just ignore it... } bs_stream = null; } discardBackingStore(); } /** * Method makeInputStream * * @return * @throws IOException * @throws FileNotFoundException */ protected InputStream makeInputStream() throws IOException, FileNotFoundException { close(); if (cache != null) { return new ByteArrayInputStream(cache.toByteArray()); } else if (bs_handle != null) { return createBackingStoreInputStream(); } else { return null; } } /** * Method finalize */ protected void finalize() { discardBuffer(); } /** * Method switchToBackingStore * * @throws IOException */ protected void switchToBackingStore() throws IOException { bs_handle = File.createTempFile("Axis", ".msg"); bs_handle.createNewFile(); bs_handle.deleteOnExit(); bs_stream = new FileOutputStream(bs_handle); bs_stream.write(cache.toByteArray()); cache = null; } /** * Method getBackingStoreFileName * * @throws IOException */ public String getBackingStoreFileName() throws IOException { String fileName = null; if (bs_handle != null) { fileName = bs_handle.getCanonicalPath(); } return fileName; } /** * Method discardBackingStore */ protected void discardBackingStore() { if (bs_handle != null) { bs_handle.delete(); bs_handle = null; } } /** * Method createBackingStoreInputStream * * @return * @throws FileNotFoundException */ protected InputStream createBackingStoreInputStream() throws FileNotFoundException { try { return new BufferedInputStream( new FileInputStream(bs_handle.getCanonicalPath())); } catch (IOException e) { throw new FileNotFoundException(bs_handle.getAbsolutePath()); } } /** * Method toByteArray * * @return * @throws IOException */ public byte[] toByteArray() throws IOException { InputStream inp = this.makeInputStream(); byte[] buf = null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); buf = new byte[WORKING_BUFFER_SIZE]; int len; while ((len = inp.read(buf, 0, WORKING_BUFFER_SIZE)) != -1) { baos.write(buf, 0, len); } inp.close(); discardBackingStore(); return baos.toByteArray(); } /** * Method writeTo * * @param os * @throws IOException */ public void writeTo(OutputStream os) throws IOException { InputStream inp = this.makeInputStream(); byte[] buf = null; buf = new byte[WORKING_BUFFER_SIZE]; int len; while ((len = inp.read(buf, 0, WORKING_BUFFER_SIZE)) != -1) { os.write(buf, 0, len); } inp.close(); discardBackingStore(); } }