From 6d59eef6e47f6266b3f64d2a90c9cbe153b8cb90 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Thu, 21 Jul 2016 23:09:07 +0000 Subject: [PATCH] Provide a createOrUpdateDocument method at the POIFS level, and use to simplify writing code #57919 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1753739 13f79535-47bb-0310-9956-ffa450edef68 --- src/java/org/apache/poi/POIDocument.java | 22 ++++--------- .../poi/hssf/usermodel/HSSFWorkbook.java | 2 +- .../poi/poifs/filesystem/DirectoryNode.java | 32 +++++++++++++++++++ .../poifs/filesystem/NPOIFSFileSystem.java | 22 +++++++++++-- 4 files changed, 59 insertions(+), 19 deletions(-) diff --git a/src/java/org/apache/poi/POIDocument.java b/src/java/org/apache/poi/POIDocument.java index 6b80bc6f43..87c6a14f66 100644 --- a/src/java/org/apache/poi/POIDocument.java +++ b/src/java/org/apache/poi/POIDocument.java @@ -21,7 +21,6 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -35,8 +34,6 @@ import org.apache.poi.hpsf.SummaryInformation; import org.apache.poi.poifs.crypt.EncryptionInfo; import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DocumentInputStream; -import org.apache.poi.poifs.filesystem.DocumentNode; -import org.apache.poi.poifs.filesystem.NPOIFSDocument; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.poifs.filesystem.OPOIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem; @@ -239,14 +236,13 @@ public abstract class POIDocument implements Closeable { /** * Writes out the updated standard Document Information Properties (HPSF) * into the currently open NPOIFSFileSystem - * TODO Implement in-place update * * @throws IOException if an error when writing to the open * {@link NPOIFSFileSystem} occurs - * TODO throws exception if open from stream not file */ protected void writeProperties() throws IOException { - throw new IllegalStateException("In-place write is not yet supported"); + validateInPlaceWritePossible(); + writeProperties(directory.getFileSystem(), null); } /** @@ -301,16 +297,9 @@ public abstract class POIDocument implements Closeable { mSet.write(bOut); byte[] data = bOut.toByteArray(); ByteArrayInputStream bIn = new ByteArrayInputStream(data); - - // New or Existing? - // TODO Use a createOrUpdate method for this to be cleaner! - try { - DocumentNode propSetNode = (DocumentNode)outFS.getRoot().getEntry(name); - NPOIFSDocument propSetDoc = new NPOIFSDocument(propSetNode); - propSetDoc.replaceContents(bIn); - } catch (FileNotFoundException e) { - outFS.createDocument(bIn,name); - } + + // Create or Update the Property Set stream in the POIFS + outFS.createOrUpdateDocument(bIn, name); logger.log(POILogger.INFO, "Wrote property set " + name + " of size " + data.length); } catch(org.apache.poi.hpsf.WritingNotSupportedException wnse) { @@ -351,6 +340,7 @@ public abstract class POIDocument implements Closeable { * @since POI 3.15 beta 3 * * @throws IOException thrown on errors writing to the file + * @throws IllegalStateException if this isn't from a writable File */ public abstract void write() throws IOException; diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index 32789ca96d..123d8d3329 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -1312,7 +1312,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss workbookDoc.replaceContents(new ByteArrayInputStream(getBytes())); // Update the properties streams in the file - writeProperties(directory.getFileSystem(), null); + writeProperties(); // Sync with the File on disk directory.getFileSystem().writeFilesystem(); diff --git a/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java b/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java index 9be71a5ccf..ccb008507b 100644 --- a/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java +++ b/src/java/org/apache/poi/poifs/filesystem/DirectoryNode.java @@ -478,6 +478,38 @@ public class DirectoryNode return rval; } + /** + * Set the contents of a document, creating if needed, + * otherwise updating. Returns the created / updated DocumentEntry + * + * @param name the name of the new or existing DocumentEntry + * @param stream the InputStream from which to populate the DocumentEntry + * + * @return the new or updated DocumentEntry + * + * @exception IOException + */ + + public DocumentEntry createOrUpdateDocument(final String name, + final InputStream stream) + throws IOException + { + if (! hasEntry(name)) { + return createDocument(name, stream); + } else { + DocumentNode existing = (DocumentNode)getEntry(name); + if (_nfilesystem != null) { + NPOIFSDocument nDoc = new NPOIFSDocument(existing); + nDoc.replaceContents(stream); + return existing; + } else { + // Do it the hard way for Old POIFS... + deleteEntry(existing); + return createDocument(name, stream); + } + } + } + /** * Gets the storage clsid of the directory entry * diff --git a/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java b/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java index e81888d06f..f987c43b31 100644 --- a/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java +++ b/src/java/org/apache/poi/poifs/filesystem/NPOIFSFileSystem.java @@ -689,8 +689,6 @@ public class NPOIFSFileSystem extends BlockStore return getRoot().createDocument(name, stream); } - // TODO Add a createOrUpdateDocument method to simplify code - /** * create a new DocumentEntry in the root entry; the data will be * provided later @@ -727,6 +725,26 @@ public class NPOIFSFileSystem extends BlockStore return getRoot().createDirectory(name); } + /** + * Set the contents of a document in the root directory, + * creating if needed, otherwise updating + * + * @param stream the InputStream from which the document's data + * will be obtained + * @param name the name of the new or existing POIFSDocument + * + * @return the new or updated DocumentEntry + * + * @exception IOException on error populating the POIFSDocument + */ + + public DocumentEntry createOrUpdateDocument(final InputStream stream, + final String name) + throws IOException + { + return getRoot().createOrUpdateDocument(name, stream); + } + /** * Does the filesystem support an in-place write via * {@link #writeFilesystem()} ? If false, only writing out to -- 2.39.5