001: /*
002: * ============================================================================
003: * GNU Lesser General Public License
004: * ============================================================================
005: *
006: * JasperReports - Free Java report-generating library.
007: * Copyright (C) 2005 Works, Inc. http://www.works.com/
008: *
009: * This library is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU Lesser General Public
011: * License as published by the Free Software Foundation; either
012: * version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * Lesser General Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
022: *
023: * Works, Inc.
024: * 6034 West Courtyard Drive
025: * Suite 210
026: * Austin, TX 78730-5032
027: * USA
028: * http://www.works.com/
029: */
030:
031: /*
032: * Licensed to JasperSoft Corporation under a Contributer Agreement
033: */
034: package net.sf.jasperreports.engine.fill;
035:
036: import java.io.BufferedInputStream;
037: import java.io.BufferedOutputStream;
038: import java.io.File;
039: import java.io.FileInputStream;
040: import java.io.FileNotFoundException;
041: import java.io.FileOutputStream;
042: import java.io.IOException;
043:
044: import net.sf.jasperreports.engine.JRRuntimeException;
045: import net.sf.jasperreports.engine.JRVirtualizable;
046: import net.sf.jasperreports.engine.util.JRProperties;
047:
048: import org.apache.commons.logging.Log;
049: import org.apache.commons.logging.LogFactory;
050:
051: /**
052: * Virtualizes data to the filesystem. When this object is finalized, it removes
053: * the swap files it makes. The virtualized objects have references to this
054: * object, so finalization does not occur until this object and the objects
055: * using it are only weakly referenced.
056: *
057: * @author John Bindel
058: * @version $Id: JRFileVirtualizer.java 1327 2006-07-06 13:43:55Z teodord $
059: */
060: public class JRFileVirtualizer extends JRAbstractLRUVirtualizer {
061:
062: private static final Log log = LogFactory
063: .getLog(JRFileVirtualizer.class);
064:
065: /**
066: * Property used to decide whether {@link File#deleteOnExit() deleteOnExit} should be requested
067: * for temporary files created by the virtualizer.
068: * <p>
069: * Calling {@link File#deleteOnExit() File.deleteOnExit()} will accumulate JVM process memory
070: * (see this <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4513817">bug</a>), and this
071: * should abviously be avoided in long-running applications.
072: * <p>
073: * Temporary files will be deleted by explicitly calling {@link #cleanup() cleanup()} or from the virtualizer
074: * <code>finalize()</code> method.
075: */
076: public static final String PROPERTY_TEMP_FILES_SET_DELETE_ON_EXIT = JRProperties.PROPERTY_PREFIX
077: + "virtualizer.files.delete.on.exit";
078:
079: private final String directory;
080:
081: /**
082: * Uses the process's working directory as the location to store files.
083: *
084: * @param maxSize
085: * the maximum size (in JRVirtualizable objects) of the paged in
086: * cache.
087: */
088: public JRFileVirtualizer(int maxSize) {
089: this (maxSize, null);
090: }
091:
092: /**
093: * @param maxSize
094: * the maximum size (in JRVirtualizable objects) of the paged in
095: * cache.
096: * @param directory
097: * the base directory in the filesystem where the paged out data
098: * is to be stored
099: */
100: public JRFileVirtualizer(int maxSize, String directory) {
101: super (maxSize);
102:
103: this .directory = directory;
104: }
105:
106: private String makeFilename(JRVirtualizable o) {
107: String uid = o.getUID();
108: return "virt" + uid;
109: }
110:
111: private String makeFilename(String virtualId) {
112: return "virt" + virtualId;
113: }
114:
115: protected void pageOut(JRVirtualizable o) throws IOException {
116: // Store data to a file.
117: String filename = makeFilename(o);
118: File file = new File(directory, filename);
119:
120: if (file.createNewFile()) {
121: if (JRProperties
122: .getBooleanProperty(PROPERTY_TEMP_FILES_SET_DELETE_ON_EXIT)) {
123: file.deleteOnExit();
124: }
125:
126: FileOutputStream fos = null;
127: try {
128: fos = new FileOutputStream(file);
129: BufferedOutputStream bufferedOut = new BufferedOutputStream(
130: fos);
131: writeData(o, bufferedOut);
132: } catch (FileNotFoundException e) {
133: log.error("Error virtualizing object", e);
134: throw new JRRuntimeException(e);
135: } finally {
136: if (fos != null) {
137: fos.close();
138: }
139: }
140: } else {
141: if (!isReadOnly(o)) {
142: throw new IllegalStateException(
143: "Cannot virtualize data because the file \""
144: + filename + "\" already exists.");
145: }
146: }
147: }
148:
149: protected void pageIn(JRVirtualizable o) throws IOException {
150: // Load data from a file.
151: String filename = makeFilename(o);
152: File file = new File(directory, filename);
153:
154: FileInputStream fis = null;
155: try {
156: fis = new FileInputStream(file);
157: BufferedInputStream bufferedIn = new BufferedInputStream(
158: fis);
159: readData(o, bufferedIn);
160: } catch (FileNotFoundException e) {
161: log.error("Error devirtualizing object", e);
162: throw new JRRuntimeException(e);
163: } finally {
164: if (fis != null) {
165: fis.close();
166: }
167: }
168:
169: if (!isReadOnly(o)) {
170: // Wait until we know it worked before tossing the data.
171: file.delete();
172: }
173: }
174:
175: protected void dispose(String virtualId) {
176: String filename = makeFilename(virtualId);
177: File file = new File(directory, filename);
178: file.delete();
179: }
180:
181: /**
182: * Called when we are done with the virtualizer and wish to
183: * cleanup any resources it has.
184: */
185: public synchronized void cleanup() {
186: disposeAll();
187: reset();
188: }
189: }
|