mirror of https://github.com/apache/poi.git
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
This commit is contained in:
parent
6c2d2ffe7f
commit
8362b74f90
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
<changes>
|
<changes>
|
||||||
<release version="3.8-beta3" date="2011-??-??">
|
<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">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">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>
|
<action dev="poi-developers" type="fix">51143 - NameCommentRecord correction for writing non ASCII strings</action>
|
||||||
|
|
|
@ -69,6 +69,9 @@ public class NPOIFSMiniStore extends BlockStore
|
||||||
it.next();
|
it.next();
|
||||||
}
|
}
|
||||||
ByteBuffer dataBlock = it.next();
|
ByteBuffer dataBlock = it.next();
|
||||||
|
if(dataBlock == null) {
|
||||||
|
throw new IndexOutOfBoundsException("Big block " + bigBlockNumber + " outside stream");
|
||||||
|
}
|
||||||
|
|
||||||
// Position ourselves, and take a slice
|
// Position ourselves, and take a slice
|
||||||
dataBlock.position(
|
dataBlock.position(
|
||||||
|
@ -83,9 +86,35 @@ public class NPOIFSMiniStore extends BlockStore
|
||||||
* Load the block, extending the underlying stream if needed
|
* Load the block, extending the underlying stream if needed
|
||||||
*/
|
*/
|
||||||
protected ByteBuffer createBlockIfNeeded(final int offset) throws IOException {
|
protected ByteBuffer createBlockIfNeeded(final int offset) throws IOException {
|
||||||
// TODO Extend the stream if needed
|
// Try to get it without extending the stream
|
||||||
// TODO Needs append support on the underlying stream
|
try {
|
||||||
return getBlockAt(offset);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
package org.apache.poi.poifs.filesystem;
|
package org.apache.poi.poifs.filesystem;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
@ -245,7 +246,80 @@ public final class TestNPOIFSMiniStore extends TestCase {
|
||||||
* big blocks that make up the ministream as needed
|
* big blocks that make up the ministream as needed
|
||||||
*/
|
*/
|
||||||
public void testCreateBlockIfNeeded() throws Exception {
|
public void testCreateBlockIfNeeded() throws Exception {
|
||||||
// TODO Add underlying implementation
|
NPOIFSFileSystem fs = new NPOIFSFileSystem(_inst.openResourceAsStream("BlockSize512.zvi"));
|
||||||
// TODO Add unit test
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -731,8 +731,61 @@ public final class TestNPOIFSStream extends TestCase {
|
||||||
assertEquals((byte)0x04, b182.get(1));
|
assertEquals((byte)0x04, b182.get(1));
|
||||||
|
|
||||||
|
|
||||||
// Write lots, so it needs another big block
|
// Write lots, so it needs another big block
|
||||||
// TODO
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue