diff --git a/src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java b/src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java index 5c753927e..308ae15c7 100644 --- a/src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java +++ b/src/java/org/apache/poi/poifs/filesystem/NPOIFSMiniStore.java @@ -86,44 +86,50 @@ public class NPOIFSMiniStore extends BlockStore * Load the block, extending the underlying stream if needed */ 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) { - int firstBigBlock = _filesystem.getFreeBlock(); - _filesystem.createBlockIfNeeded(firstBigBlock); - _filesystem.setNextBlock(firstBigBlock, POIFSConstants.END_OF_CHAIN); - _filesystem._get_property_table().getRoot().setStartBlock(firstBigBlock); - _mini_stream = new NPOIFSStream(_filesystem, firstBigBlock); + firstInStore = true; } - + // 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); + if (! firstInStore) { + 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); + + // 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); } /** diff --git a/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSFileSystem.java b/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSFileSystem.java index 6d51e5591..0e531ea93 100644 --- a/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSFileSystem.java +++ b/src/testcases/org/apache/poi/poifs/filesystem/TestNPOIFSFileSystem.java @@ -414,6 +414,7 @@ public final class TestNPOIFSFileSystem { // We have one BAT at block 99 assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(99)); + assertBATCount(fs, 1, 0); // We've spare ones from 100 to 128 for(int i=100; i<128; i++) { @@ -652,6 +653,8 @@ public final class TestNPOIFSFileSystem { // Check it's all there // TODO Add check + + // TODO Something about directories too // All done fs.close(); @@ -663,8 +666,12 @@ public final class TestNPOIFSFileSystem { * Then, add some streams, write and read */ @Test + @SuppressWarnings("resource") public void createWriteRead() throws Exception { NPOIFSFileSystem fs = new NPOIFSFileSystem(); + NDocumentInputStream inp; + DocumentEntry miniDoc; + DocumentEntry normDoc; // Initially has a BAT but not SBAT assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(0)); @@ -822,8 +829,30 @@ if(1==0) { // TODO FIX // 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 fs.close(); @@ -963,9 +992,48 @@ if(1==0) { // TODO FIX // 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 - // TODO + // Add to the main stream + 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)); } - - // TODO Directory/Document create/write/read/delete/change tests }