Package net.sf.jasperreports.engine.util

Source Code of net.sf.jasperreports.engine.util.FileBufferedOutputStream$DataStream

/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2009 Jaspersoft Corporation. All rights reserved.
* http://www.jaspersoft.com
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
* the following license terms apply:
*
* This program is part of JasperReports.
*
* JasperReports is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* JasperReports is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with JasperReports. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.jasperreports.engine.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
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;

import net.sf.jasperreports.engine.JRRuntimeException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


/**
* @author Lucian Chirita (lucianc@users.sourceforge.net)
* @version $Id: FileBufferedOutputStream.java 3717 2010-04-09 10:01:33Z teodord $
*/
public class FileBufferedOutputStream extends OutputStream
{
 
  private static final Log log = LogFactory.getLog(FileBufferedOutputStream.class);
 
  /**
   * Specifies the maximum in-memory buffer length that triggers the creation of a temporary file on disk to store further content sent to this output stream. 
   */
  public static final String PROPERTY_MEMORY_THRESHOLD = JRProperties.PROPERTY_PREFIX + "file.buffer.os.memory.threshold";
  //public static final int DEFAULT_MEMORY_THRESHOLD = 1 << 18;
  public static final int INFINIT_MEMORY_THRESHOLD = -1;
  public static final int DEFAULT_INITIAL_MEMORY_BUFFER_SIZE = 1 << 16;
  public static final int DEFAULT_INPUT_BUFFER_LENGTH = 1 << 14;
 
  private final int memoryThreshold;
  private final int initialMemoryBufferSize;
  private final int inputBufferLength;
 
  private final ByteArrayOutputStream memoryOutput;
  private int size;
  private File file;
  private BufferedOutputStream fileOutput;
  private boolean closed;
  private boolean disposed;
 
  public FileBufferedOutputStream() {
    this(JRProperties.getIntegerProperty(PROPERTY_MEMORY_THRESHOLD, INFINIT_MEMORY_THRESHOLD), DEFAULT_INITIAL_MEMORY_BUFFER_SIZE, DEFAULT_INPUT_BUFFER_LENGTH);
  }
 
  public FileBufferedOutputStream(int memoryThreshold) {
    this(memoryThreshold, DEFAULT_INITIAL_MEMORY_BUFFER_SIZE, DEFAULT_INPUT_BUFFER_LENGTH);
  }
 
  public FileBufferedOutputStream(int memoryThreshold, int initialMemoryBufferSize) {
    this(memoryThreshold, initialMemoryBufferSize, DEFAULT_INPUT_BUFFER_LENGTH);
  }
 
  public FileBufferedOutputStream(int memoryThreshold, int initialMemoryBufferSize, int inputBufferLength) {
    this.memoryThreshold = memoryThreshold;
    this.initialMemoryBufferSize = initialMemoryBufferSize;
    this.inputBufferLength = inputBufferLength;
   
    size = 0;
    if (this.memoryThreshold == 0)
    {
      memoryOutput = null;
    }
    else
    {
      int initialSize = this.initialMemoryBufferSize;
      if (initialSize > this.memoryThreshold)
      {
        initialSize = this.memoryThreshold;
      }
      memoryOutput = new ByteArrayOutputStream(initialSize);
    }
  }

  public void write(int b) throws IOException {
    checkClosed();
   
    if (availableMemorySpace() > 0) {
      memoryOutput.write(b);
    } else {
      ensureFileOutput().write(b);
    }
   
    ++size;
  }

  protected int availableMemorySpace() {
    int availableMemorySpace;
    if (memoryOutput != null
        && (memoryThreshold < 0 || memoryOutput.size() < memoryThreshold)) {
      availableMemorySpace = memoryThreshold - memoryOutput.size();
    } else {
      availableMemorySpace = 0;
    }
    return availableMemorySpace;
  }
 
  protected BufferedOutputStream ensureFileOutput() throws IOException, FileNotFoundException {
    if (fileOutput == null) {
      file = File.createTempFile("file.buff.os.", ".tmp");
      FileOutputStream fileOutputStream = new FileOutputStream(file);
      fileOutput = new BufferedOutputStream(fileOutputStream);
    }
    return fileOutput;
  }

  public void write(byte[] b, int off, int len) throws IOException {
    checkClosed();
   
    int memoryLen = availableMemorySpace();
    if (len < memoryLen) {
      memoryLen = len;
    }
   
    if (memoryLen > 0) {
      memoryOutput.write(b, off, memoryLen);
    }
   
    if (memoryLen < len) {
      ensureFileOutput().write(b, off + memoryLen, len - memoryLen);
    }
   
    size += len;
  }

  public void checkClosed() {
    if (closed) {
      throw new JRRuntimeException("Output stream already closed.");
    }
  }

  public void close() throws IOException {
    if (!closed && fileOutput != null) {
      fileOutput.flush();
      fileOutput.close();
    }
   
    closed = true;
  }

  public void flush() throws IOException {
    if (fileOutput != null) {
      fileOutput.flush();
    }
  }

  public int size() {
    return size;
  }
 
  public void writeData(OutputStream out) throws IOException {
    if (!closed) {
      close();
    }

    if (memoryOutput != null) {
      memoryOutput.writeTo(out);
    }
   
    if (file != null) {
      FileInputStream fileInput = new FileInputStream(file);
      boolean inputClosed = false;
      try {
        byte[] buffer = new byte[inputBufferLength];
        int read;
        while((read = fileInput.read(buffer)) > 0) {
          out.write(buffer, 0, read);
        }
        fileInput.close();
        inputClosed = true;
      } finally {
        if (!inputClosed) {
          try {
            fileInput.close();
          } catch (IOException e) {
            log.warn("Could not close file input stream", e);
          }
        }
      }
    }
  }
 
  public void dispose() {
    if (disposed) {
      return;
    }
   
    boolean success = true;
    if (!closed && fileOutput != null) {
      try {
        fileOutput.close();
      } catch (IOException e) {
        log.warn("Error while closing the temporary file output stream", e);
        success = false;
      }
    }
   
    if (file != null && !file.delete()) {
      log.warn("Error while deleting the temporary file");
      success = false;
    }
   
    disposed = success;
  }

  protected void finalize() throws Throwable //NOSONAR
  {
    dispose();
    super.finalize();
  }
 
  public InputStream getDataInputStream() throws IOException
  {
    if (!closed)
    {
      close();
    }
   
    return new DataStream();
  }
 
  protected class DataStream extends InputStream
  {
    private int memoryIdx;
    private final byte[] memoryData;
    private final InputStream fileInput;
   
    public DataStream() throws FileNotFoundException
    {
      memoryIdx = 0;
      memoryData = memoryOutput == null ? new byte[0] : memoryOutput.toByteArray();
      fileInput = file == null ? null : new BufferedInputStream(new FileInputStream(file));
    }
   
    public synchronized int read() throws IOException
    {
      int read;
      if (memoryIdx < memoryData.length)
      {
        read = memoryData[memoryIdx] & 0xff;
        ++memoryIdx;
      }
      else if (fileInput != null)
      {
        read = fileInput.read();
      }
      else
      {
        read = -1;
      }
      return read;
    }
   
    public synchronized int read(byte b[], int off, int len) throws IOException
    {
      if (len <= 0)
      {
        return 0;
      }
     
      int read;
      if (memoryIdx < memoryData.length)
      {
        read = len;
        if (read > memoryData.length - memoryIdx)
        {
          read = memoryData.length - memoryIdx;
        }
       
        System.arraycopy(memoryData, memoryIdx, b, off, read);
        memoryIdx += read;
      }
      else
      {
        read = 0;
      }
     
      if (read < len && fileInput != null)
      {
        int readFile = fileInput.read(b, off + read, len - read);
        if (readFile > 0)
        {
          read += readFile;
        }
      }
     
      return read == 0 ? -1 : read;
    }

    public void close() throws IOException
    {
      if (fileInput != null)
      {
        fileInput.close();
      }
    }

    public synchronized int available() throws IOException
    {
      int available = memoryData.length - memoryIdx;
      if (fileInput != null)
      {
        available += fileInput.available();
      }
      return available;
    }

    public synchronized long skip(long n) throws IOException
    {
      if (n <= 0)
      {
        return 0;
      }
     
      long skipped;
      if (memoryIdx < memoryData.length)
      {
        skipped = n;
        if (skipped > memoryData.length - memoryIdx)
        {
          skipped = memoryData.length - memoryIdx;
        }
       
        memoryIdx += skipped;
      }
      else
      {
        skipped = 0;
      }
     
      if (skipped < n && fileInput != null)
      {
        skipped += fileInput.skip(n - skipped);
      }
     
      return skipped;
    }
   
  }
}
TOP

Related Classes of net.sf.jasperreports.engine.util.FileBufferedOutputStream$DataStream

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.