From 73bc57db7476d41de217adef4478d56d7909ea36 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Fri, 25 Apr 2014 23:34:09 +0000 Subject: [PATCH] NDocumentOutputStream write logic git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1590191 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/hpsf/MutablePropertySet.java | 3 + .../apache/poi/hpsf/SpecialPropertySet.java | 8 -- .../filesystem/NDocumentOutputStream.java | 83 ++++++++++++++++++- .../poi/poifs/filesystem/NPOIFSDocument.java | 5 ++ .../org/apache/poi/hpsf/basic/TestWrite.java | 3 +- 5 files changed, 88 insertions(+), 14 deletions(-) diff --git a/src/java/org/apache/poi/hpsf/MutablePropertySet.java b/src/java/org/apache/poi/hpsf/MutablePropertySet.java index 2604cbe32..304141113 100644 --- a/src/java/org/apache/poi/hpsf/MutablePropertySet.java +++ b/src/java/org/apache/poi/hpsf/MutablePropertySet.java @@ -246,6 +246,9 @@ public class MutablePropertySet extends PropertySet final MutableSection s = (MutableSection) i.next(); offset += s.write(out); } + + /* Indicate that we're done */ + out.close(); } diff --git a/src/java/org/apache/poi/hpsf/SpecialPropertySet.java b/src/java/org/apache/poi/hpsf/SpecialPropertySet.java index 993765f6a..4bcd8ca71 100644 --- a/src/java/org/apache/poi/hpsf/SpecialPropertySet.java +++ b/src/java/org/apache/poi/hpsf/SpecialPropertySet.java @@ -261,8 +261,6 @@ public abstract class SpecialPropertySet extends MutablePropertySet delegate.write(dir, name); } - - /** * @see org.apache.poi.hpsf.MutablePropertySet#write(java.io.OutputStream) */ @@ -271,8 +269,6 @@ public abstract class SpecialPropertySet extends MutablePropertySet delegate.write(out); } - - /** * @see org.apache.poi.hpsf.PropertySet#equals(java.lang.Object) */ @@ -281,8 +277,6 @@ public abstract class SpecialPropertySet extends MutablePropertySet return delegate.equals(o); } - - /** * @see org.apache.poi.hpsf.PropertySet#getProperties() */ @@ -291,8 +285,6 @@ public abstract class SpecialPropertySet extends MutablePropertySet return delegate.getProperties(); } - - /** * @see org.apache.poi.hpsf.PropertySet#getProperty(int) */ diff --git a/src/java/org/apache/poi/poifs/filesystem/NDocumentOutputStream.java b/src/java/org/apache/poi/poifs/filesystem/NDocumentOutputStream.java index 021500947..6d4d13d5d 100644 --- a/src/java/org/apache/poi/poifs/filesystem/NDocumentOutputStream.java +++ b/src/java/org/apache/poi/poifs/filesystem/NDocumentOutputStream.java @@ -18,9 +18,13 @@ package org.apache.poi.poifs.filesystem; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; +import org.apache.poi.poifs.common.POIFSConstants; +import org.apache.poi.poifs.property.DocumentProperty; + /** * This class provides methods to write a DocumentEntry managed by a * {@link NPOIFSFileSystem} instance. @@ -34,6 +38,16 @@ public final class NDocumentOutputStream extends OutputStream { /** the actual Document */ private NPOIFSDocument _document; + /** and its Property */ + private DocumentProperty _property; + + /** our buffer, when null we're into normal blocks */ + private ByteArrayOutputStream _buffer = + new ByteArrayOutputStream(POIFSConstants.BIG_BLOCK_MINIMUM_DOCUMENT_SIZE); + + /** our main block stream, when we're into normal blocks */ + private NPOIFSStream _stream; + private OutputStream _stream_output; /** * Create an OutputStream from the specified DocumentEntry. @@ -48,6 +62,8 @@ public final class NDocumentOutputStream extends OutputStream { _document_size = 0; _closed = false; + _property = (DocumentProperty)((DocumentNode)document).getProperty(); + _document = new NPOIFSDocument((DocumentNode)document); _document.free(); } @@ -67,22 +83,81 @@ public final class NDocumentOutputStream extends OutputStream { // Have an empty one created for now DocumentEntry doc = parent.createDocument(name, new ByteArrayInputStream(new byte[0])); + _property = (DocumentProperty)((DocumentNode)doc).getProperty(); _document = new NPOIFSDocument((DocumentNode)doc); } + + private void dieIfClosed() throws IOException { + if (_closed) { + throw new IOException("cannot perform requested operation on a closed stream"); + } + } + + private void checkBufferSize() throws IOException { + // Have we gone over the mini stream limit yet? + if (_buffer.size() > POIFSConstants.BIG_BLOCK_MINIMUM_DOCUMENT_SIZE) { + // Will need to be in the main stream + byte[] data = _buffer.toByteArray(); + _buffer = null; + write(data, 0, data.length); + } else { + // So far, mini stream will work, keep going + } + } public void write(int b) throws IOException { - // TODO + dieIfClosed(); + + if (_buffer != null) { + _buffer.write(b); + checkBufferSize(); + } else { + write(new byte[] { (byte)b }); + } } public void write(byte[] b) throws IOException { - // TODO + dieIfClosed(); + + if (_buffer != null) { + _buffer.write(b); + checkBufferSize(); + } else { + write(b, 0, b.length); + } } public void write(byte[] b, int off, int len) throws IOException { - // TODO + dieIfClosed(); + + if (_buffer != null) { + _buffer.write(b, off, len); + checkBufferSize(); + } else { + if (_stream == null) { + _stream = new NPOIFSStream(_document.getFileSystem()); + _stream_output = _stream.getOutputStream(); + } + _stream_output.write(b, off, len); + _document_size += len; + } } public void close() throws IOException { - // TODO + // Do we have a pending buffer for the mini stream? + if (_buffer != null) { + // It's not much data, so ask NPOIFSDocument to do it for us + _document.replaceContents(new ByteArrayInputStream(_buffer.toByteArray())); + } + else { + // We've been writing to the stream as we've gone along + // Update the details on the property now + _stream_output.close(); + _property.updateSize(_document_size); + _property.setStartBlock(_stream.getStartBlock()); + } + + // No more! + _closed = true; } } diff --git a/src/java/org/apache/poi/poifs/filesystem/NPOIFSDocument.java b/src/java/org/apache/poi/poifs/filesystem/NPOIFSDocument.java index affaa1612..99613c5ea 100644 --- a/src/java/org/apache/poi/poifs/filesystem/NPOIFSDocument.java +++ b/src/java/org/apache/poi/poifs/filesystem/NPOIFSDocument.java @@ -154,6 +154,11 @@ public final class NPOIFSDocument implements POIFSViewable { _property.setStartBlock(POIFSConstants.END_OF_CHAIN); } + NPOIFSFileSystem getFileSystem() + { + return _filesystem; + } + int getDocumentBlockSize() { return _block_size; } diff --git a/src/testcases/org/apache/poi/hpsf/basic/TestWrite.java b/src/testcases/org/apache/poi/hpsf/basic/TestWrite.java index 8e228f687..e4cf9b5eb 100644 --- a/src/testcases/org/apache/poi/hpsf/basic/TestWrite.java +++ b/src/testcases/org/apache/poi/hpsf/basic/TestWrite.java @@ -799,9 +799,8 @@ public class TestWrite extends TestCase /** * 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 { + public void DISABLEDtestInPlaceNPOIFSWrite() throws Exception { NPOIFSFileSystem fs = null; DirectoryEntry root = null; DocumentNode sinfDoc = null;