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
868a108fe3
commit
c3769b5da0
@ -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 {
|
public void replaceContents(InputStream stream) throws IOException {
|
||||||
free();
|
free();
|
||||||
store(stream);
|
int size = store(stream);
|
||||||
|
_property.setStartBlock(_stream.getStartBlock());
|
||||||
|
_property.updateSize(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -120,6 +120,14 @@ public class DocumentProperty
|
|||||||
|
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the size of the property's data
|
||||||
|
*/
|
||||||
|
public void updateSize(int size)
|
||||||
|
{
|
||||||
|
setSize(size);
|
||||||
|
}
|
||||||
|
|
||||||
/* ********** END extension of Property ********** */
|
/* ********** END extension of Property ********** */
|
||||||
} // end public class DocumentProperty
|
} // end public class DocumentProperty
|
||||||
|
@ -17,7 +17,16 @@
|
|||||||
|
|
||||||
package org.apache.poi.hpsf.basic;
|
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.nio.charset.Charset;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -26,14 +35,37 @@ import java.util.Map;
|
|||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.apache.poi.POIDataSamples;
|
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.PropertyIDMap;
|
||||||
import org.apache.poi.hpsf.wellknown.SectionIDMap;
|
import org.apache.poi.hpsf.wellknown.SectionIDMap;
|
||||||
import org.apache.poi.poifs.eventfilesystem.POIFSReader;
|
import org.apache.poi.poifs.eventfilesystem.POIFSReader;
|
||||||
import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
|
import org.apache.poi.poifs.eventfilesystem.POIFSReaderEvent;
|
||||||
import org.apache.poi.poifs.eventfilesystem.POIFSReaderListener;
|
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.poifs.filesystem.POIFSFileSystem;
|
||||||
import org.apache.poi.util.CodePageUtil;
|
import org.apache.poi.util.CodePageUtil;
|
||||||
|
import org.apache.poi.util.IOUtils;
|
||||||
import org.apache.poi.util.LittleEndian;
|
import org.apache.poi.util.LittleEndian;
|
||||||
import org.apache.poi.util.TempFile;
|
import org.apache.poi.util.TempFile;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
@ -764,6 +796,106 @@ public class TestWrite extends TestCase
|
|||||||
assertEquals(ps1, ps2);
|
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(mini3, (DocumentEntry)testDir.getEntry("Mini3"));
|
||||||
assertContentsMatches(main4096, (DocumentEntry)testDir.getEntry("Normal4096"));
|
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
|
// All done
|
||||||
fs.close();
|
fs.close();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user