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
This commit is contained in:
Nick Burch 2016-07-21 23:09:07 +00:00
parent 50519d3c73
commit 13a7be6cd2
4 changed files with 59 additions and 19 deletions

View File

@ -21,7 +21,6 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.Closeable; import java.io.Closeable;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; 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.crypt.EncryptionInfo;
import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.DocumentInputStream; 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.NPOIFSFileSystem;
import org.apache.poi.poifs.filesystem.OPOIFSFileSystem; import org.apache.poi.poifs.filesystem.OPOIFSFileSystem;
import org.apache.poi.poifs.filesystem.POIFSFileSystem; 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) * Writes out the updated standard Document Information Properties (HPSF)
* into the currently open NPOIFSFileSystem * into the currently open NPOIFSFileSystem
* TODO Implement in-place update
* *
* @throws IOException if an error when writing to the open * @throws IOException if an error when writing to the open
* {@link NPOIFSFileSystem} occurs * {@link NPOIFSFileSystem} occurs
* TODO throws exception if open from stream not file
*/ */
protected void writeProperties() throws IOException { 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); mSet.write(bOut);
byte[] data = bOut.toByteArray(); byte[] data = bOut.toByteArray();
ByteArrayInputStream bIn = new ByteArrayInputStream(data); ByteArrayInputStream bIn = new ByteArrayInputStream(data);
// New or Existing? // Create or Update the Property Set stream in the POIFS
// TODO Use a createOrUpdate method for this to be cleaner! outFS.createOrUpdateDocument(bIn, name);
try {
DocumentNode propSetNode = (DocumentNode)outFS.getRoot().getEntry(name);
NPOIFSDocument propSetDoc = new NPOIFSDocument(propSetNode);
propSetDoc.replaceContents(bIn);
} catch (FileNotFoundException e) {
outFS.createDocument(bIn,name);
}
logger.log(POILogger.INFO, "Wrote property set " + name + " of size " + data.length); logger.log(POILogger.INFO, "Wrote property set " + name + " of size " + data.length);
} catch(org.apache.poi.hpsf.WritingNotSupportedException wnse) { } catch(org.apache.poi.hpsf.WritingNotSupportedException wnse) {
@ -351,6 +340,7 @@ public abstract class POIDocument implements Closeable {
* @since POI 3.15 beta 3 * @since POI 3.15 beta 3
* *
* @throws IOException thrown on errors writing to the file * @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; public abstract void write() throws IOException;

View File

@ -1312,7 +1312,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss
workbookDoc.replaceContents(new ByteArrayInputStream(getBytes())); workbookDoc.replaceContents(new ByteArrayInputStream(getBytes()));
// Update the properties streams in the file // Update the properties streams in the file
writeProperties(directory.getFileSystem(), null); writeProperties();
// Sync with the File on disk // Sync with the File on disk
directory.getFileSystem().writeFilesystem(); directory.getFileSystem().writeFilesystem();

View File

@ -478,6 +478,38 @@ public class DirectoryNode
return rval; 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 * Gets the storage clsid of the directory entry
* *

View File

@ -689,8 +689,6 @@ public class NPOIFSFileSystem extends BlockStore
return getRoot().createDocument(name, stream); 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 * create a new DocumentEntry in the root entry; the data will be
* provided later * provided later
@ -727,6 +725,26 @@ public class NPOIFSFileSystem extends BlockStore
return getRoot().createDirectory(name); 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 * Does the filesystem support an in-place write via
* {@link #writeFilesystem()} ? If false, only writing out to * {@link #writeFilesystem()} ? If false, only writing out to