More NPOIFS mini stream improvements, and more tests for it all

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1590098 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2014-04-25 18:39:31 +00:00
parent e4e0e93ff5
commit 6a89a9afbf
2 changed files with 111 additions and 39 deletions

View File

@ -86,44 +86,50 @@ 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 {
// If we are the first block to be allocated, initialise the stream boolean firstInStore = false;
if (_mini_stream.getStartBlock() == POIFSConstants.END_OF_CHAIN) { if (_mini_stream.getStartBlock() == POIFSConstants.END_OF_CHAIN) {
int firstBigBlock = _filesystem.getFreeBlock(); firstInStore = true;
_filesystem.createBlockIfNeeded(firstBigBlock);
_filesystem.setNextBlock(firstBigBlock, POIFSConstants.END_OF_CHAIN);
_filesystem._get_property_table().getRoot().setStartBlock(firstBigBlock);
_mini_stream = new NPOIFSStream(_filesystem, firstBigBlock);
} }
// Try to get it without extending the stream // Try to get it without extending the stream
try { if (! firstInStore) {
return getBlockAt(offset); try {
} catch(IndexOutOfBoundsException e) { return getBlockAt(offset);
// Need to extend the stream } catch(IndexOutOfBoundsException e) {}
// 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);
} }
// 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);
// If we are the first block to be allocated, initialise the stream
if (firstInStore) {
_filesystem._get_property_table().getRoot().setStartBlock(newBigBlock);
_mini_stream = new NPOIFSStream(_filesystem, newBigBlock);
} else {
// 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);
}
// This is now the new end
_filesystem.setNextBlock(newBigBlock, POIFSConstants.END_OF_CHAIN);
// Now try again, to get the real small block
return createBlockIfNeeded(offset);
} }
/** /**

View File

@ -414,6 +414,7 @@ public final class TestNPOIFSFileSystem {
// We have one BAT at block 99 // We have one BAT at block 99
assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(99)); assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(99));
assertBATCount(fs, 1, 0);
// We've spare ones from 100 to 128 // We've spare ones from 100 to 128
for(int i=100; i<128; i++) { for(int i=100; i<128; i++) {
@ -652,6 +653,8 @@ public final class TestNPOIFSFileSystem {
// Check it's all there // Check it's all there
// TODO Add check // TODO Add check
// TODO Something about directories too
// All done // All done
fs.close(); fs.close();
@ -663,8 +666,12 @@ public final class TestNPOIFSFileSystem {
* Then, add some streams, write and read * Then, add some streams, write and read
*/ */
@Test @Test
@SuppressWarnings("resource")
public void createWriteRead() throws Exception { public void createWriteRead() throws Exception {
NPOIFSFileSystem fs = new NPOIFSFileSystem(); NPOIFSFileSystem fs = new NPOIFSFileSystem();
NDocumentInputStream inp;
DocumentEntry miniDoc;
DocumentEntry normDoc;
// Initially has a BAT but not SBAT // Initially has a BAT but not SBAT
assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(0)); assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(0));
@ -822,8 +829,30 @@ if(1==0) { // TODO FIX
// Check some data // Check some data
// TODO assertEquals(1, fs.getRoot().getEntryCount());
testDir = (DirectoryEntry)fs.getRoot().getEntry("Test Directory");
assertEquals(3, testDir.getEntryCount());
miniDoc = (DocumentEntry)testDir.getEntry("Mini");
inp = new NDocumentInputStream(miniDoc);
byte[] miniRead = new byte[miniDoc.getSize()];
assertEquals(miniDoc.getSize(), inp.read(miniRead));
assertThat(mini, equalTo(miniRead));
inp.close();
normDoc = (DocumentEntry)testDir.getEntry("Normal4096");
inp = new NDocumentInputStream(normDoc);
byte[] normRead = new byte[normDoc.getSize()];
assertEquals(normDoc.getSize(), inp.read(normRead));
assertThat(main4096, equalTo(normRead));
inp.close();
normDoc = (DocumentEntry)testDir.getEntry("Normal5124");
inp = new NDocumentInputStream(normDoc);
normRead = new byte[normDoc.getSize()];
assertEquals(normDoc.getSize(), inp.read(normRead));
assertThat(main5124, equalTo(normRead));
inp.close();
// All done // All done
fs.close(); fs.close();
@ -963,9 +992,48 @@ if(1==0) { // TODO FIX
// Add one more stream to each, then save and re-load // Add one more stream to each, then save and re-load
byte[] mini2 = new byte[] { -42, 0, -1, -2, -3, -4, -42 };
testDir.createDocument("Mini2", new ByteArrayInputStream(mini2));
// Recheck // Add to the main stream
// TODO byte[] main4106 = new byte[4106];
main4106[0] = 41;
main4106[4105] = 42;
testDir.createDocument("Normal4106", new ByteArrayInputStream(main4106));
// Recheck the data in all 4 streams
fs = writeOutAndReadBack(fs);
fsRoot = fs.getRoot();
assertEquals(1, fsRoot.getEntryCount());
parentDir = (DirectoryEntry)fsRoot.getEntry("Parent Directory");
assertEquals(1, parentDir.getEntryCount());
testDir = (DirectoryEntry)parentDir.getEntry("Test Directory");
assertEquals(4, testDir.getEntryCount());
miniDoc = (DocumentEntry)testDir.getEntry("Mini");
inp = new NDocumentInputStream(miniDoc);
miniRead = new byte[miniDoc.getSize()];
assertEquals(miniDoc.getSize(), inp.read(miniRead));
assertThat(mini, equalTo(miniRead));
inp.close();
miniDoc = (DocumentEntry)testDir.getEntry("Mini2");
inp = new NDocumentInputStream(miniDoc);
miniRead = new byte[miniDoc.getSize()];
assertEquals(miniDoc.getSize(), inp.read(miniRead));
assertThat(mini2, equalTo(miniRead));
inp.close();
normDoc = (DocumentEntry)testDir.getEntry("Normal4106");
inp = new NDocumentInputStream(normDoc);
normRead = new byte[normDoc.getSize()];
assertEquals(normDoc.getSize(), inp.read(normRead));
assertThat(main4106, equalTo(normRead));
inp.close();
} }
/** /**
@ -991,6 +1059,4 @@ if(1==0) { // TODO FIX
assertThat(wbDataExp, equalTo(wbDataAct)); assertThat(wbDataExp, equalTo(wbDataAct));
} }
// TODO Directory/Document create/write/read/delete/change tests
} }