From 5a1ff54cf303be82b6418ed28efe87df307d52c7 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Thu, 21 Jul 2016 23:25:02 +0000 Subject: [PATCH] In-place write for HSLF #57919 git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1753741 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/hslf/record/CurrentUserAtom.java | 2 +- .../poi/hslf/usermodel/HSLFSlideShowImpl.java | 47 ++++++++++++++----- .../org/apache/poi/hslf/TestReWrite.java | 12 ++++- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/scratchpad/src/org/apache/poi/hslf/record/CurrentUserAtom.java b/src/scratchpad/src/org/apache/poi/hslf/record/CurrentUserAtom.java index ef187de5a..2d688603a 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/record/CurrentUserAtom.java +++ b/src/scratchpad/src/org/apache/poi/hslf/record/CurrentUserAtom.java @@ -279,6 +279,6 @@ public class CurrentUserAtom new ByteArrayInputStream(baos.toByteArray()); // Write out - fs.createDocument(bais,"Current User"); + fs.createOrUpdateDocument(bais,"Current User"); } } diff --git a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java index 1adfcff06..4e4c28d2b 100644 --- a/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java +++ b/src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java @@ -537,16 +537,37 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable { // Update and write out the Current User atom int oldLastUserEditAtomPos = (int)currentUser.getCurrentEditOffset(); Integer newLastUserEditAtomPos = oldToNewPositions.get(oldLastUserEditAtomPos); - if(newLastUserEditAtomPos == null || usr.getLastOnDiskOffset() != newLastUserEditAtomPos) { + if (newLastUserEditAtomPos == null || usr.getLastOnDiskOffset() != newLastUserEditAtomPos) { throw new HSLFException("Couldn't find the new location of the last UserEditAtom that used to be at " + oldLastUserEditAtomPos); } currentUser.setCurrentEditOffset(usr.getLastOnDiskOffset()); - } - - @Override - public void write() throws IOException { - throw new IllegalStateException("In-Place write coming soon! See Bug #57919"); - } + } + + /** + * Writes out the slideshow to the currently open file. + * + *

This will fail (with an {@link IllegalStateException} if the + * slideshow was opened read-only, opened from an {@link InputStream} + * instead of a File, or if this is not the root document. For those cases, + * you must use {@link #write(OutputStream)} or {@link #write(File)} to + * write to a brand new document. + * + * @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 + */ + @Override + public void write() throws IOException { + validateInPlaceWritePossible(); + + // Write the PowerPoint streams to the current FileSystem + // No need to do anything to other streams, already there! + write(directory.getFileSystem(), false); + + // Sync with the File on disk + directory.getFileSystem().writeFilesystem(); + } /** * Writes out the slideshow file the is represented by an instance @@ -625,7 +646,7 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable { outFS.close(); } } - private void write(POIFSFileSystem outFS, boolean preserveNodes) throws IOException { + private void write(NPOIFSFileSystem outFS, boolean copyAllOtherNodes) throws IOException { // read properties and pictures, with old encryption settings where appropriate if (_pictures == null) { readPictures(); @@ -656,7 +677,7 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable { // Write the PPT stream into the POIFS layer ByteArrayInputStream bais = new ByteArrayInputStream(_docstream); - outFS.createDocument(bais,"PowerPoint Document"); + outFS.createOrUpdateDocument(bais,"PowerPoint Document"); writtenEntries.add("PowerPoint Document"); currentUser.setEncrypted(encryptedSS.getDocumentEncryptionAtom() != null); @@ -671,15 +692,15 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable { p.write(pict); encryptedSS.encryptPicture(pict.getBuf(), offset); } - outFS.createDocument( + outFS.createOrUpdateDocument( new ByteArrayInputStream(pict.getBuf(), 0, pict.size()), "Pictures" ); writtenEntries.add("Pictures"); pict.close(); } - // If requested, write out any other streams we spot - if (preserveNodes) { + // If requested, copy over any other streams we spot, eg Macros + if (copyAllOtherNodes) { EntryUtils.copyNodes(directory.getFileSystem(), outFS, writtenEntries); } } @@ -706,7 +727,7 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable { * @throws IOException if an error when writing to the * {@link POIFSFileSystem} occurs */ - protected void writeProperties(POIFSFileSystem outFS, List writtenEntries) throws IOException { + protected void writeProperties(NPOIFSFileSystem outFS, List writtenEntries) throws IOException { super.writeProperties(outFS, writtenEntries); DocumentEncryptionAtom dea = getDocumentEncryptionAtom(); if (dea != null) { diff --git a/src/scratchpad/testcases/org/apache/poi/hslf/TestReWrite.java b/src/scratchpad/testcases/org/apache/poi/hslf/TestReWrite.java index 06bfd1798..e54cc0cac 100644 --- a/src/scratchpad/testcases/org/apache/poi/hslf/TestReWrite.java +++ b/src/scratchpad/testcases/org/apache/poi/hslf/TestReWrite.java @@ -79,7 +79,9 @@ public final class TestReWrite { hss.write(baos); final File file = TempFile.createTempFile("TestHSLF", ".ppt"); + final File file2 = TempFile.createTempFile("TestHSLF", ".ppt"); hss.write(file); + hss.write(file2); // Build an input stream of it, and read back as a POIFS from the stream @@ -89,7 +91,15 @@ public final class TestReWrite { // And the same on the temp file POIFSFileSystem npfF = new POIFSFileSystem(file); - for (POIFSFileSystem npf : new POIFSFileSystem[] { npfS, npfF }) { + // And another where we do an in-place write + POIFSFileSystem npfRF = new POIFSFileSystem(file2, false); + HSLFSlideShowImpl hssRF = new HSLFSlideShowImpl(npfRF); + hssRF.write(); + hssRF.close(); + npfRF = new POIFSFileSystem(file2); + + // Check all of them in turn + for (POIFSFileSystem npf : new POIFSFileSystem[] { npfS, npfF, npfRF }) { // Check that the "PowerPoint Document" sections have the same size DocumentEntry oProps = (DocumentEntry)pfs.getRoot().getEntry("PowerPoint Document"); DocumentEntry nProps = (DocumentEntry)npf.getRoot().getEntry("PowerPoint Document");