mirror of https://github.com/apache/poi.git
Begin to support and test in-place changes to documents within a NPOIFS stream
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1590185 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
9d2023f2ac
commit
6bf09f5b16
|
@ -0,0 +1,88 @@
|
|||
/* ====================================================================
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.poifs.filesystem;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* This class provides methods to write a DocumentEntry managed by a
|
||||
* {@link NPOIFSFileSystem} instance.
|
||||
*/
|
||||
public final class NDocumentOutputStream extends OutputStream {
|
||||
/** the Document's size */
|
||||
private int _document_size;
|
||||
|
||||
/** have we been closed? */
|
||||
private boolean _closed;
|
||||
|
||||
/** the actual Document */
|
||||
private NPOIFSDocument _document;
|
||||
|
||||
/**
|
||||
* Create an OutputStream from the specified DocumentEntry.
|
||||
* The specified entry will be emptied.
|
||||
*
|
||||
* @param document the DocumentEntry to be written
|
||||
*/
|
||||
public NDocumentOutputStream(DocumentEntry document) throws IOException {
|
||||
if (!(document instanceof DocumentNode)) {
|
||||
throw new IOException("Cannot open internal document storage, " + document + " not a Document Node");
|
||||
}
|
||||
_document_size = 0;
|
||||
_closed = false;
|
||||
|
||||
_document = new NPOIFSDocument((DocumentNode)document);
|
||||
_document.free();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an OutputStream to create the specified new Entry
|
||||
*
|
||||
* @param parent Where to create the Entry
|
||||
* @param name Name of the new entry
|
||||
*/
|
||||
public NDocumentOutputStream(DirectoryEntry parent, String name) throws IOException {
|
||||
if (!(parent instanceof DirectoryNode)) {
|
||||
throw new IOException("Cannot open internal directory storage, " + parent + " not a Directory Node");
|
||||
}
|
||||
_document_size = 0;
|
||||
_closed = false;
|
||||
|
||||
// Have an empty one created for now
|
||||
DocumentEntry doc = parent.createDocument(name, new ByteArrayInputStream(new byte[0]));
|
||||
_document = new NPOIFSDocument((DocumentNode)doc);
|
||||
}
|
||||
|
||||
public void write(int b) throws IOException {
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void write(byte[] b) throws IOException {
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
// TODO
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
// TODO
|
||||
}
|
||||
}
|
|
@ -176,7 +176,9 @@ public final class NPOIFSDocument implements POIFSViewable {
|
|||
|
||||
public void replaceContents(InputStream stream) throws IOException {
|
||||
free();
|
||||
store(stream);
|
||||
int size = store(stream);
|
||||
_property.setStartBlock(_stream.getStartBlock());
|
||||
_property.updateSize(size);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -120,6 +120,14 @@ public class DocumentProperty
|
|||
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the size of the property's data
|
||||
*/
|
||||
public void updateSize(int size)
|
||||
{
|
||||
setSize(size);
|
||||
}
|
||||
|
||||
/* ********** END extension of Property ********** */
|
||||
} // end public class DocumentProperty
|
||||
|
|
|
@ -17,7 +17,16 @@
|
|||
|
||||
package org.apache.poi.hpsf.basic;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
|
@ -26,14 +35,37 @@ import java.util.Map;
|
|||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.poi.POIDataSamples;
|
||||
import org.apache.poi.hpsf.*;
|
||||
import org.apache.poi.hpsf.ClassID;
|
||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||
import org.apache.poi.hpsf.HPSFException;
|
||||
import org.apache.poi.hpsf.IllegalPropertySetDataException;
|
||||
import org.apache.poi.hpsf.MutableProperty;
|
||||
import org.apache.poi.hpsf.MutablePropertySet;
|
||||
import org.apache.poi.hpsf.MutableSection;
|
||||
import org.apache.poi.hpsf.NoFormatIDException;
|
||||
import org.apache.poi.hpsf.NoPropertySetStreamException;
|
||||
import org.apache.poi.hpsf.PropertySet;
|
||||
import org.apache.poi.hpsf.PropertySetFactory;
|
||||
import org.apache.poi.hpsf.ReadingNotSupportedException;
|
||||
import org.apache.poi.hpsf.Section;
|
||||
import org.apache.poi.hpsf.SummaryInformation;
|
||||
import org.apache.poi.hpsf.UnsupportedVariantTypeException;
|
||||
import org.apache.poi.hpsf.Variant;
|
||||
import org.apache.poi.hpsf.VariantSupport;
|
||||
import org.apache.poi.hpsf.WritingNotSupportedException;
|
||||
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
|
||||
import org.apache.poi.hpsf.wellknown.SectionIDMap;
|
||||
import org.apache.poi.poifs.eventfilesystem.POIFSReader;
|
||||
import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
|
||||
import org.apache.poi.poifs.eventfilesystem.POIFSReaderListener;
|
||||
import org.apache.poi.poifs.filesystem.DirectoryEntry;
|
||||
import org.apache.poi.poifs.filesystem.DocumentNode;
|
||||
import org.apache.poi.poifs.filesystem.NDocumentInputStream;
|
||||
import org.apache.poi.poifs.filesystem.NDocumentOutputStream;
|
||||
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
|
||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||
import org.apache.poi.util.CodePageUtil;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.LittleEndian;
|
||||
import org.apache.poi.util.TempFile;
|
||||
import org.junit.Assert;
|
||||
|
@ -764,6 +796,106 @@ public class TestWrite extends TestCase
|
|||
assertEquals(ps1, ps2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that when using NPOIFS, we can do an in-place write
|
||||
* without needing to stream in + out the whole kitchen sink
|
||||
* TODO Finish implementing the logic for this
|
||||
*/
|
||||
public void DISBALEDtestInPlaceNPOIFSWrite() throws Exception {
|
||||
NPOIFSFileSystem fs = null;
|
||||
DirectoryEntry root = null;
|
||||
DocumentNode sinfDoc = null;
|
||||
DocumentNode dinfDoc = null;
|
||||
SummaryInformation sinf = null;
|
||||
DocumentSummaryInformation dinf = null;
|
||||
|
||||
final File copy = TempFile.createTempFile("Test-HPSF", "ole2");
|
||||
copy.deleteOnExit();
|
||||
|
||||
// Copy a test file over to a temp location
|
||||
InputStream inp = _samples.openResourceAsStream("TestShiftJIS.doc");
|
||||
FileOutputStream out = new FileOutputStream(copy);
|
||||
IOUtils.copy(inp, out);
|
||||
inp.close();
|
||||
out.close();
|
||||
|
||||
// Open the copy in read/write mode
|
||||
fs = new NPOIFSFileSystem(copy);
|
||||
root = fs.getRoot();
|
||||
|
||||
// Read the properties in there
|
||||
sinfDoc = (DocumentNode)root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
|
||||
sinf = (SummaryInformation)PropertySetFactory.create(new NDocumentInputStream(sinfDoc));
|
||||
assertEquals(131077, sinf.getOSVersion());
|
||||
|
||||
dinfDoc = (DocumentNode)root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
dinf = (DocumentSummaryInformation)PropertySetFactory.create(new NDocumentInputStream(dinfDoc));
|
||||
assertEquals(131077, dinf.getOSVersion());
|
||||
|
||||
// Check they start as we expect
|
||||
assertEquals("Reiichiro Hori", sinf.getAuthor());
|
||||
assertEquals("Microsoft Word 9.0", sinf.getApplicationName());
|
||||
assertEquals("\u7b2c1\u7ae0", sinf.getTitle());
|
||||
|
||||
assertEquals("", dinf.getCompany());
|
||||
assertEquals(null, dinf.getManager());
|
||||
|
||||
// Alter a few of them
|
||||
sinf.setAuthor("Changed Author");
|
||||
sinf.setTitle("Le titre \u00e9tait chang\u00e9");
|
||||
dinf.setManager("Changed Manager");
|
||||
|
||||
|
||||
// Save this into the filesystem
|
||||
sinf.write(new NDocumentOutputStream(sinfDoc));
|
||||
dinf.write(new NDocumentOutputStream(dinfDoc));
|
||||
|
||||
|
||||
// Read as-is
|
||||
sinfDoc = (DocumentNode)root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
|
||||
sinf = (SummaryInformation)PropertySetFactory.create(new NDocumentInputStream(sinfDoc));
|
||||
assertEquals(131077, sinf.getOSVersion());
|
||||
|
||||
dinfDoc = (DocumentNode)root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
dinf = (DocumentSummaryInformation)PropertySetFactory.create(new NDocumentInputStream(dinfDoc));
|
||||
assertEquals(131077, dinf.getOSVersion());
|
||||
|
||||
assertEquals("Changed Author", sinf.getAuthor());
|
||||
assertEquals("Microsoft Word 9.0", sinf.getApplicationName());
|
||||
assertEquals("Le titre \u00e9tait chang\u00e9", sinf.getTitle());
|
||||
|
||||
assertEquals("", dinf.getCompany());
|
||||
assertEquals("Changed Manager", dinf.getManager());
|
||||
|
||||
|
||||
// Close, re-load
|
||||
fs.writeFilesystem();
|
||||
fs.close();
|
||||
|
||||
fs = new NPOIFSFileSystem(copy);
|
||||
root = fs.getRoot();
|
||||
|
||||
// Re-check on load
|
||||
sinfDoc = (DocumentNode)root.getEntry(SummaryInformation.DEFAULT_STREAM_NAME);
|
||||
sinf = (SummaryInformation)PropertySetFactory.create(new NDocumentInputStream(sinfDoc));
|
||||
assertEquals(131077, sinf.getOSVersion());
|
||||
|
||||
dinfDoc = (DocumentNode)root.getEntry(DocumentSummaryInformation.DEFAULT_STREAM_NAME);
|
||||
dinf = (DocumentSummaryInformation)PropertySetFactory.create(new NDocumentInputStream(dinfDoc));
|
||||
assertEquals(131077, dinf.getOSVersion());
|
||||
|
||||
assertEquals("Changed Author", sinf.getAuthor());
|
||||
assertEquals("Microsoft Word 9.0", sinf.getApplicationName());
|
||||
assertEquals("Le titre \u00e9tait chang\u00e9", sinf.getTitle());
|
||||
|
||||
assertEquals("", dinf.getCompany());
|
||||
assertEquals("Changed Manager", dinf.getManager());
|
||||
|
||||
|
||||
// Tidy up
|
||||
fs.close();
|
||||
copy.delete();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -862,6 +862,43 @@ public final class TestNPOIFSFileSystem {
|
|||
assertContentsMatches(mini3, (DocumentEntry)testDir.getEntry("Mini3"));
|
||||
assertContentsMatches(main4096, (DocumentEntry)testDir.getEntry("Normal4096"));
|
||||
|
||||
|
||||
// Change some existing streams
|
||||
NPOIFSDocument mini2Doc = new NPOIFSDocument((DocumentNode)testDir.getEntry("Mini2"));
|
||||
mini2Doc.replaceContents(new ByteArrayInputStream(mini));
|
||||
|
||||
byte[] main4106 = new byte[4106];
|
||||
main4106[0] = 41;
|
||||
main4106[4105] = 42;
|
||||
NPOIFSDocument mainDoc = new NPOIFSDocument((DocumentNode)testDir.getEntry("Normal4096"));
|
||||
mainDoc.replaceContents(new ByteArrayInputStream(main4106));
|
||||
|
||||
|
||||
// Re-check
|
||||
fs = writeOutAndReadBack(fs);
|
||||
|
||||
root = fs.getRoot();
|
||||
testDir = (DirectoryEntry)root.getEntry("Testing 123");
|
||||
|
||||
assertEquals(5, root.getEntryCount());
|
||||
assertThat(root.getEntryNames(), hasItem("Thumbnail"));
|
||||
assertThat(root.getEntryNames(), hasItem("Image"));
|
||||
assertThat(root.getEntryNames(), hasItem("Testing 123"));
|
||||
assertThat(root.getEntryNames(), hasItem("\u0005DocumentSummaryInformation"));
|
||||
assertThat(root.getEntryNames(), hasItem("\u0005SummaryInformation"));
|
||||
|
||||
assertEquals(5, testDir.getEntryCount());
|
||||
assertThat(testDir.getEntryNames(), hasItem("Mini2"));
|
||||
assertThat(testDir.getEntryNames(), hasItem("Mini3"));
|
||||
assertThat(testDir.getEntryNames(), hasItem("Normal4096"));
|
||||
assertThat(testDir.getEntryNames(), hasItem("Testing 789"));
|
||||
assertThat(testDir.getEntryNames(), hasItem("Testing ABC"));
|
||||
|
||||
assertContentsMatches(mini, (DocumentEntry)testDir.getEntry("Mini2"));
|
||||
assertContentsMatches(mini3, (DocumentEntry)testDir.getEntry("Mini3"));
|
||||
assertContentsMatches(main4106, (DocumentEntry)testDir.getEntry("Normal4096"));
|
||||
|
||||
|
||||
// All done
|
||||
fs.close();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue