1 21 package com.jaspersoft.jasperserver.war.common; 22 23 import java.io.BufferedOutputStream ; 24 import java.io.ByteArrayOutputStream ; 25 import java.io.File ; 26 import java.io.FileInputStream ; 27 import java.io.FileNotFoundException ; 28 import java.io.FileOutputStream ; 29 import java.io.IOException ; 30 import java.io.OutputStream ; 31 32 import org.apache.commons.logging.Log; 33 import org.apache.commons.logging.LogFactory; 34 35 import com.jaspersoft.jasperserver.api.JSException; 36 37 41 public class FileBufferedOutputStream extends OutputStream { 42 43 private static final Log log = LogFactory.getLog(FileBufferedOutputStream.class); 44 45 public static final int DEFAULT_MEMORY_THRESHOLD = 1 << 18; 46 public static final int INFINIT_MEMORY_THRESHOLD = -1; 47 public static final int DEFAULT_INITIAL_MEMORY_BUFFER_SIZE = 1 << 16; 48 public static final int DEFAULT_INPUT_BUFFER_LENGTH = 1 << 14; 49 50 private final int memoryThreshold; 51 private final int initialMemoryBufferSize; 52 private final int inputBufferLenght; 53 54 private final ByteArrayOutputStream memoryOutput; 55 private int size; 56 private File file; 57 private BufferedOutputStream fileOutput; 58 private boolean closed; 59 private boolean disposed; 60 61 public FileBufferedOutputStream() { 62 this(DEFAULT_MEMORY_THRESHOLD, DEFAULT_INITIAL_MEMORY_BUFFER_SIZE, DEFAULT_INPUT_BUFFER_LENGTH); 63 } 64 65 public FileBufferedOutputStream(int memoryThreshold) { 66 this(memoryThreshold, DEFAULT_INITIAL_MEMORY_BUFFER_SIZE, DEFAULT_INPUT_BUFFER_LENGTH); 67 } 68 69 public FileBufferedOutputStream(int memoryThreshold, int initialMemoryBufferSize) { 70 this(memoryThreshold, initialMemoryBufferSize, DEFAULT_INPUT_BUFFER_LENGTH); 71 } 72 73 public FileBufferedOutputStream(int memoryThreshold, int initialMemoryBufferSize, int inputBufferLenght) { 74 this.memoryThreshold = memoryThreshold; 75 this.initialMemoryBufferSize = initialMemoryBufferSize; 76 this.inputBufferLenght = inputBufferLenght; 77 78 size = 0; 79 memoryOutput = this.memoryThreshold != 0 ? new ByteArrayOutputStream (this.initialMemoryBufferSize) : null; 80 } 81 82 public void write(int b) throws IOException { 83 checkClosed(); 84 85 if (availableMemorySpace() > 0) { 86 memoryOutput.write(b); 87 } else { 88 ensureFileOutput().write(b); 89 } 90 91 ++size; 92 } 93 94 protected int availableMemorySpace() { 95 int availableMemorySpace; 96 if (memoryOutput != null 97 && (memoryThreshold < 0 || memoryOutput.size() < memoryThreshold)) { 98 availableMemorySpace = memoryThreshold - memoryOutput.size(); 99 } else { 100 availableMemorySpace = 0; 101 } 102 return availableMemorySpace; 103 } 104 105 protected BufferedOutputStream ensureFileOutput() throws IOException , FileNotFoundException { 106 if (fileOutput == null) { 107 file = File.createTempFile("exported_report", ".tmp"); 108 FileOutputStream fileOutputStream = new FileOutputStream (file); 109 fileOutput = new BufferedOutputStream (fileOutputStream); 110 } 111 return fileOutput; 112 } 113 114 public void write(byte[] b, int off, int len) throws IOException { 115 checkClosed(); 116 117 int memoryLen = availableMemorySpace(); 118 if (len < memoryLen) { 119 memoryLen = len; 120 } 121 122 if (memoryLen > 0) { 123 memoryOutput.write(b, off, memoryLen); 124 } 125 126 if (memoryLen < len) { 127 ensureFileOutput().write(b, off + memoryLen, len - memoryLen); 128 } 129 130 size += len; 131 } 132 133 public void checkClosed() { 134 if (closed) { 135 throw new JSException("Output stream already closed"); 136 } 137 } 138 139 public void close() throws IOException { 140 if (!closed && fileOutput != null) { 141 fileOutput.flush(); 142 fileOutput.close(); 143 } 144 145 closed = true; 146 } 147 148 public void flush() throws IOException { 149 if (fileOutput != null) { 150 fileOutput.flush(); 151 } 152 } 153 154 public int size() { 155 return size; 156 } 157 158 public void writeData(OutputStream out) throws IOException { 159 if (!closed) { 160 close(); 161 } 162 163 if (memoryOutput != null) { 164 memoryOutput.writeTo(out); 165 } 166 167 if (file != null) { 168 FileInputStream fileInput = new FileInputStream (file); 169 boolean inputClosed = false; 170 try { 171 byte[] buffer = new byte[inputBufferLenght]; 172 int read; 173 while((read = fileInput.read(buffer)) > 0) { 174 out.write(buffer, 0, read); 175 } 176 fileInput.close(); 177 inputClosed = true; 178 } finally { 179 if (!inputClosed) { 180 try { 181 fileInput.close(); 182 } catch (IOException e) { 183 log.warn("Could not close file input stream", e); 184 } 185 } 186 } 187 } 188 } 189 190 public void dispose() { 191 if (disposed) { 192 return; 193 } 194 195 boolean success = true; 196 if (!closed && fileOutput != null) { 197 try { 198 fileOutput.close(); 199 } catch (IOException e) { 200 log.warn("Error while closing the temporary file output stream", e); 201 success = false; 202 } 203 } 204 205 if (file != null && !file.delete()) { 206 log.warn("Error while deleting the temporary file"); 207 success = false; 208 } 209 210 disposed = success; 211 } 212 213 protected void finalize() throws Throwable { 214 dispose(); 215 super.finalize(); 216 } 217 218 219 } 220 | Popular Tags |