* 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);
+ 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...
- // Now try again to get it
- return createBlockIfNeeded(offset);
+ // 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);
}
/**
// 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++) {
// Check it's all there
// TODO Add check
+
+ // TODO Something about directories too
// All done
fs.close();
* 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));
// 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();
// 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));
+
+ // 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());
- // Recheck
- // TODO
+ 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();
}
/**
assertThat(wbDataExp, equalTo(wbDataAct));
}
-
- // TODO Directory/Document create/write/read/delete/change tests
}