From e9b76ce3b1b960ee6e3f7b7ce30eaa024b20366d Mon Sep 17 00:00:00 2001 From: PJ Fanning Date: Sat, 9 Oct 2021 13:12:15 +0000 Subject: [PATCH] [bug-64542] allow file channel closing to be controlled by calling code git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1894068 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/poifs/filesystem/POIFSFileSystem.java | 31 ++++++++++++++++--- .../poi/poifs/nio/FileBackedDataSource.java | 18 ++++++++--- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/poi/src/main/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java b/poi/src/main/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java index ebee94394b..1a625f38d0 100644 --- a/poi/src/main/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java +++ b/poi/src/main/java/org/apache/poi/poifs/filesystem/POIFSFileSystem.java @@ -164,7 +164,7 @@ public class POIFSFileSystem extends BlockStore */ public POIFSFileSystem(File file, boolean readOnly) throws IOException { - this(null, file, readOnly, true); + this(null, file, readOnly, true, true); } /** @@ -198,12 +198,33 @@ public class POIFSFileSystem extends BlockStore */ public POIFSFileSystem(FileChannel channel, boolean readOnly) throws IOException { - this(channel, null, readOnly, false); + this(channel, null, readOnly, false, true); } - @SuppressWarnings("java:S2095") - private POIFSFileSystem(FileChannel channel, File srcFile, boolean readOnly, boolean closeChannelOnError) + /** + *

Creates a POIFSFileSystem from an open FileChannel. This uses + * less memory than creating from an InputStream.

+ * + *

Note that with this constructor, you will need to call {@link #close()} + * when you're done to have the underlying resources closed. The closeChannel + * parameter controls whether the provided channel is closed.

+ * + * @param channel the FileChannel from which to read or read/write the data + * @param readOnly whether the POIFileSystem will only be used in read-only mode + * @param closeChannel whether the provided FileChannel should be closed when + * {@link #close()} is called, or when this constructor throws + * an exception + * @throws IOException on errors reading, or on invalid data + * @since POI 5.1.0 + */ + public POIFSFileSystem(FileChannel channel, boolean readOnly, boolean closeChannel) throws IOException { + this(channel, null, readOnly, closeChannel, closeChannel); + } + + @SuppressWarnings("java:S2095") + private POIFSFileSystem(FileChannel channel, File srcFile, boolean readOnly, boolean closeChannelOnError, + boolean closeChannelOnClose) throws IOException { this(false); try { @@ -216,7 +237,7 @@ public class POIFSFileSystem extends BlockStore channel = d.getChannel(); _data = d; } else { - _data = new FileBackedDataSource(channel, readOnly); + _data = new FileBackedDataSource(channel, readOnly, closeChannelOnClose); } // Get the header diff --git a/poi/src/main/java/org/apache/poi/poifs/nio/FileBackedDataSource.java b/poi/src/main/java/org/apache/poi/poifs/nio/FileBackedDataSource.java index e3001f238f..31e439fb5d 100644 --- a/poi/src/main/java/org/apache/poi/poifs/nio/FileBackedDataSource.java +++ b/poi/src/main/java/org/apache/poi/poifs/nio/FileBackedDataSource.java @@ -43,6 +43,7 @@ public class FileBackedDataSource extends DataSource implements Closeable { private Long channelSize; private final boolean writable; + private final boolean closeChannelOnClose; // remember file base, which needs to be closed too private final RandomAccessFile srcFile; @@ -64,19 +65,28 @@ public class FileBackedDataSource extends DataSource implements Closeable { } public FileBackedDataSource(RandomAccessFile srcFile, boolean readOnly) { - this(srcFile, srcFile.getChannel(), readOnly); + this(srcFile, srcFile.getChannel(), readOnly, false); } public FileBackedDataSource(FileChannel channel, boolean readOnly) { - this(null, channel, readOnly); + this(channel, readOnly, true); } - private FileBackedDataSource(RandomAccessFile srcFile, FileChannel channel, boolean readOnly) { + /** + * @since POI 5.1.0 + */ + public FileBackedDataSource(FileChannel channel, boolean readOnly, boolean closeChannelOnClose) { + this(null, channel, readOnly, closeChannelOnClose); + } + + private FileBackedDataSource(RandomAccessFile srcFile, FileChannel channel, boolean readOnly, boolean closeChannelOnClose) { this.srcFile = srcFile; this.channel = channel; this.writable = !readOnly; + this.closeChannelOnClose = closeChannelOnClose; } + public boolean isWriteable() { return this.writable; } @@ -170,7 +180,7 @@ public class FileBackedDataSource extends DataSource implements Closeable { if (srcFile != null) { // see http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4796385 srcFile.close(); - } else { + } else if (closeChannelOnClose) { channel.close(); } } -- 2.39.5