aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNick Burch <nick@apache.org>2011-05-12 21:00:04 +0000
committerNick Burch <nick@apache.org>2011-05-12 21:00:04 +0000
commit8362b74f90cb31d09bf5ab3e31dcad23510f4e1e (patch)
treeb6f98e10420dbf97ad3f0bc9d554f67316819eaa /src
parent6c2d2ffe7fd9af4ff0614752736f164f338d937c (diff)
downloadpoi-8362b74f90cb31d09bf5ab3e31dcad23510f4e1e.tar.gz
poi-8362b74f90cb31d09bf5ab3e31dcad23510f4e1e.zip
Finish NPOIFS support for writing to mini streams where the big block stream needs extending, and unit tests
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1102458 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src')
-rw-r--r--src/documentation/content/xdocs/status.xml1
-rw-r--r--src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java35
-rw-r--r--src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSMiniStore.java78
-rw-r--r--src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSStream.java57
4 files changed, 164 insertions, 7 deletions
diff --git a/src/documentation/content/xdocs/status.xml b/src/documentation/content/xdocs/status.xml
index cc0b65671f..db3adb4e1b 100644
--- a/src/documentation/content/xdocs/status.xml
+++ b/src/documentation/content/xdocs/status.xml
@@ -34,6 +34,7 @@
<changes>
<release version="3.8-beta3" date="2011-??-??">
+ <action dev="poi-developers" type="add">NPOIFS Mini Streams now support extending the underlying big block stream to fit more data</action>
<action dev="poi-developers" type="fix">51148 - XWPFDocument now properly tracks paragraphs and tables when adding/removing them</action>
<action dev="poi-developers" type="fix">51153 - Correct sizing of LbsDataSubRecord with unused padding fields</action>
<action dev="poi-developers" type="fix">51143 - NameCommentRecord correction for writing non ASCII strings</action>
diff --git a/src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java b/src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java
index 6d43c3f714..33d0b25418 100644
--- a/src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java
+++ b/src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java
@@ -69,6 +69,9 @@ public class NPOIFSMiniStore extends BlockStore
it.next();
}
ByteBuffer dataBlock = it.next();
+ if(dataBlock == null) {
+ throw new IndexOutOfBoundsException("Big block " + bigBlockNumber + " outside stream");
+ }
// Position ourselves, and take a slice
dataBlock.position(
@@ -83,9 +86,35 @@ public class NPOIFSMiniStore extends BlockStore
* Load the block, extending the underlying stream if needed
*/
protected ByteBuffer createBlockIfNeeded(final int offset) throws IOException {
- // TODO Extend the stream if needed
- // TODO Needs append support on the underlying stream
- return getBlockAt(offset);
+ // Try to get it without extending the stream
+ try {
+ return getBlockAt(offset);
+ } catch(IndexOutOfBoundsException e) {
+ // Need to extend the stream
+ // TODO Replace this with proper append support
+ // For now, do the extending by hand...
+
+ // Ask for another block
+ int newBigBlock = _filesystem.getFreeBlock();
+ _filesystem.createBlockIfNeeded(newBigBlock);
+
+ // Tack it onto the end of our chain
+ ChainLoopDetector loopDetector = _filesystem.getChainLoopDetector();
+ int block = _mini_stream.getStartBlock();
+ while(true) {
+ loopDetector.claim(block);
+ int next = _filesystem.getNextBlock(block);
+ if(next == POIFSConstants.END_OF_CHAIN) {
+ break;
+ }
+ block = next;
+ }
+ _filesystem.setNextBlock(block, newBigBlock);
+ _filesystem.setNextBlock(newBigBlock, POIFSConstants.END_OF_CHAIN);
+
+ // Now try again to get it
+ return createBlockIfNeeded(offset);
+ }
}
/**
diff --git a/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSMiniStore.java b/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSMiniStore.java
index 8f495903b7..90daf160aa 100644
--- a/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSMiniStore.java
+++ b/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSMiniStore.java
@@ -18,6 +18,7 @@
package org.apache.poi.poifs.filesystem;
import java.nio.ByteBuffer;
+import java.util.Iterator;
import junit.framework.TestCase;
@@ -245,7 +246,80 @@ public final class TestNPOIFSMiniStore extends TestCase {
* big blocks that make up the ministream as needed
*/
public void testCreateBlockIfNeeded() throws Exception {
- // TODO Add underlying implementation
- // TODO Add unit test
+ NPOIFSFileSystem fs = new NPOIFSFileSystem(_inst.openResourceAsStream("BlockSize512.zvi"));
+ NPOIFSMiniStore ministore = fs.getMiniStore();
+
+ // 178 -> 179 -> 180, 181+ is free
+ assertEquals(179 , ministore.getNextBlock(178));
+ assertEquals(180 , ministore.getNextBlock(179));
+ assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(180));
+ for(int i=181; i<256; i++) {
+ assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(i));
+ }
+
+ // However, the ministore data only covers blocks to 183
+ for(int i=0; i<=183; i++) {
+ ministore.getBlockAt(i);
+ }
+ try {
+ ministore.getBlockAt(184);
+ fail("No block at 184");
+ } catch(IndexOutOfBoundsException e) {}
+
+ // The ministore itself is made up of 23 big blocks
+ Iterator<ByteBuffer> it = new NPOIFSStream(fs, fs.getRoot().getProperty().getStartBlock()).getBlockIterator();
+ int count = 0;
+ while(it.hasNext()) {
+ count++;
+ it.next();
+ }
+ assertEquals(23, count);
+
+ // Ask it to get block 184 with creating, it will do
+ ministore.createBlockIfNeeded(184);
+
+ // The ministore should be one big block bigger now
+ it = new NPOIFSStream(fs, fs.getRoot().getProperty().getStartBlock()).getBlockIterator();
+ count = 0;
+ while(it.hasNext()) {
+ count++;
+ it.next();
+ }
+ assertEquals(24, count);
+
+ // The mini block block counts now run to 191
+ for(int i=0; i<=191; i++) {
+ ministore.getBlockAt(i);
+ }
+ try {
+ ministore.getBlockAt(192);
+ fail("No block at 192");
+ } catch(IndexOutOfBoundsException e) {}
+
+
+ // Now try writing through to 192, check that the SBAT and blocks are there
+ byte[] data = new byte[15*64];
+ NPOIFSStream stream = new NPOIFSStream(ministore, 178);
+ stream.updateContents(data);
+
+ // Check now
+ assertEquals(179 , ministore.getNextBlock(178));
+ assertEquals(180 , ministore.getNextBlock(179));
+ assertEquals(181 , ministore.getNextBlock(180));
+ assertEquals(182 , ministore.getNextBlock(181));
+ assertEquals(183 , ministore.getNextBlock(182));
+ assertEquals(184 , ministore.getNextBlock(183));
+ assertEquals(185 , ministore.getNextBlock(184));
+ assertEquals(186 , ministore.getNextBlock(185));
+ assertEquals(187 , ministore.getNextBlock(186));
+ assertEquals(188 , ministore.getNextBlock(187));
+ assertEquals(189 , ministore.getNextBlock(188));
+ assertEquals(190 , ministore.getNextBlock(189));
+ assertEquals(191 , ministore.getNextBlock(190));
+ assertEquals(192 , ministore.getNextBlock(191));
+ assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(192));
+ for(int i=193; i<256; i++) {
+ assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(i));
+ }
}
}
diff --git a/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSStream.java b/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSStream.java
index ca9dd6677b..256037100c 100644
--- a/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSStream.java
+++ b/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSStream.java
@@ -731,8 +731,61 @@ public final class TestNPOIFSStream extends TestCase {
assertEquals((byte)0x04, b182.get(1));
- // Write lots, so it needs another big block
- // TODO
+ // Write lots, so it needs another big block
+ ministore.getBlockAt(183);
+ try {
+ ministore.getBlockAt(184);
+ fail("Block 184 should be off the end of the list");
+ } catch(IndexOutOfBoundsException e) {}
+
+ data = new byte[64*6 + 12];
+ for(int i=0; i<data.length; i++) {
+ data[i] = (byte)(i+1);
+ }
+ stream = new NPOIFSStream(ministore, 178);
+ stream.updateContents(data);
+
+ // Should have added 2 more blocks to the chain
+ assertEquals(179, ministore.getNextBlock(178));
+ assertEquals(180, ministore.getNextBlock(179));
+ assertEquals(181, ministore.getNextBlock(180));
+ assertEquals(182, ministore.getNextBlock(181));
+ assertEquals(183, ministore.getNextBlock(182));
+ assertEquals(184, ministore.getNextBlock(183));
+ assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(184));
+ assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(185));
+
+ // Block 184 should exist
+ ministore.getBlockAt(183);
+ ministore.getBlockAt(184);
+ ministore.getBlockAt(185);
+
+ // Check contents
+ stream = new NPOIFSStream(ministore, 178);
+ it = stream.getBlockIterator();
+ b178 = it.next();
+ b179 = it.next();
+ b180 = it.next();
+ b181 = it.next();
+ b182 = it.next();
+ ByteBuffer b183 = it.next();
+ ByteBuffer b184 = it.next();
+ assertEquals(false, it.hasNext());
+
+ assertEquals((byte)0x01, b178.get(0));
+ assertEquals((byte)0x02, b178.get(1));
+ assertEquals((byte)0x41, b179.get(0));
+ assertEquals((byte)0x42, b179.get(1));
+ assertEquals((byte)0x81, b180.get(0));
+ assertEquals((byte)0x82, b180.get(1));
+ assertEquals((byte)0xc1, b181.get(0));
+ assertEquals((byte)0xc2, b181.get(1));
+ assertEquals((byte)0x01, b182.get(0));
+ assertEquals((byte)0x02, b182.get(1));
+ assertEquals((byte)0x41, b183.get(0));
+ assertEquals((byte)0x42, b183.get(1));
+ assertEquals((byte)0x81, b184.get(0));
+ assertEquals((byte)0x82, b184.get(1));
}
/**