Search in sources :

Example 1 with BATBlock

use of org.apache.poi.poifs.storage.BATBlock in project poi by apache.

the class NPOIFSFileSystem method readBAT.

private void readBAT(int batAt, ChainLoopDetector loopDetector) throws IOException {
    loopDetector.claim(batAt);
    ByteBuffer fatData = getBlockAt(batAt);
    BATBlock bat = BATBlock.createBATBlock(bigBlockSize, fatData);
    bat.setOurBlockIndex(batAt);
    _bat_blocks.add(bat);
}
Also used : BATBlock(org.apache.poi.poifs.storage.BATBlock) ByteBuffer(java.nio.ByteBuffer)

Example 2 with BATBlock

use of org.apache.poi.poifs.storage.BATBlock in project poi by apache.

the class TestPOIFSFileSystem method testBATandXBAT.

/**
	 * Tests that we can write and read a file that contains XBATs
	 *  as well as regular BATs.
	 * However, because a file needs to be at least 6.875mb big
	 *  to have an XBAT in it, we don't have a test one. So, generate it.
	 */
public void testBATandXBAT() throws Exception {
    byte[] hugeStream = new byte[8 * 1024 * 1024];
    OPOIFSFileSystem fs = new OPOIFSFileSystem();
    fs.getRoot().createDocument("BIG", new ByteArrayInputStream(hugeStream));
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    fs.writeFilesystem(baos);
    byte[] fsData = baos.toByteArray();
    // Check the header was written properly
    InputStream inp = new ByteArrayInputStream(fsData);
    HeaderBlock header = new HeaderBlock(inp);
    assertEquals(109 + 21, header.getBATCount());
    assertEquals(1, header.getXBATCount());
    // We should have 21 BATs in the XBAT
    ByteBuffer xbatData = ByteBuffer.allocate(512);
    xbatData.put(fsData, (1 + header.getXBATIndex()) * 512, 512);
    xbatData.position(0);
    BATBlock xbat = BATBlock.createBATBlock(POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS, xbatData);
    for (int i = 0; i < 21; i++) {
        assertTrue(xbat.getValueAt(i) != POIFSConstants.UNUSED_BLOCK);
    }
    for (int i = 21; i < 127; i++) {
        assertEquals(POIFSConstants.UNUSED_BLOCK, xbat.getValueAt(i));
    }
    assertEquals(POIFSConstants.END_OF_CHAIN, xbat.getValueAt(127));
    // Load the blocks and check with that
    RawDataBlockList blockList = new RawDataBlockList(inp, POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS);
    // Header not counted
    assertEquals(fsData.length / 512, blockList.blockCount() + 1);
    new BlockAllocationTableReader(header.getBigBlockSize(), header.getBATCount(), header.getBATArray(), header.getXBATCount(), header.getXBATIndex(), blockList);
    // Header not counted
    assertEquals(fsData.length / 512, blockList.blockCount() + 1);
    // Now load it and check
    fs = null;
    fs = new OPOIFSFileSystem(new ByteArrayInputStream(fsData));
    DirectoryNode root = fs.getRoot();
    assertEquals(1, root.getEntryCount());
    DocumentNode big = (DocumentNode) root.getEntry("BIG");
    assertEquals(hugeStream.length, big.getSize());
}
Also used : HeaderBlock(org.apache.poi.poifs.storage.HeaderBlock) ByteArrayInputStream(java.io.ByteArrayInputStream) InputStream(java.io.InputStream) ByteArrayOutputStream(java.io.ByteArrayOutputStream) ByteBuffer(java.nio.ByteBuffer) RawDataBlockList(org.apache.poi.poifs.storage.RawDataBlockList) BlockAllocationTableReader(org.apache.poi.poifs.storage.BlockAllocationTableReader) ByteArrayInputStream(java.io.ByteArrayInputStream) BATBlock(org.apache.poi.poifs.storage.BATBlock)

Example 3 with BATBlock

use of org.apache.poi.poifs.storage.BATBlock in project poi by apache.

the class OPOIFSFileSystem method writeFilesystem.

/**
     * Write the filesystem out
     *
     * @param stream the OutputStream to which the filesystem will be
     *               written
     *
     * @exception IOException thrown on errors writing to the stream
     */
public void writeFilesystem(final OutputStream stream) throws IOException {
    // get the property table ready
    _property_table.preWrite();
    // create the small block store, and the SBAT
    SmallBlockTableWriter sbtw = new SmallBlockTableWriter(bigBlockSize, _documents, _property_table.getRoot());
    // create the block allocation table
    BlockAllocationTableWriter bat = new BlockAllocationTableWriter(bigBlockSize);
    // create a list of BATManaged objects: the documents plus the
    // property table and the small block table
    List<Object> bm_objects = new ArrayList<Object>();
    bm_objects.addAll(_documents);
    bm_objects.add(_property_table);
    bm_objects.add(sbtw);
    bm_objects.add(sbtw.getSBAT());
    // walk the list, allocating space for each and assigning each
    // a starting block number
    Iterator<Object> iter = bm_objects.iterator();
    while (iter.hasNext()) {
        BATManaged bmo = (BATManaged) iter.next();
        int block_count = bmo.countBlocks();
        if (block_count != 0) {
            bmo.setStartBlock(bat.allocateSpace(block_count));
        } else {
        // Either the BATManaged object is empty or its data
        // is composed of SmallBlocks; in either case,
        // allocating space in the BAT is inappropriate
        }
    }
    // allocate space for the block allocation table and take its
    // starting block
    int batStartBlock = bat.createBlocks();
    // get the extended block allocation table blocks
    HeaderBlockWriter header_block_writer = new HeaderBlockWriter(bigBlockSize);
    BATBlock[] xbat_blocks = header_block_writer.setBATBlocks(bat.countBlocks(), batStartBlock);
    // set the property table start block
    header_block_writer.setPropertyStart(_property_table.getStartBlock());
    // set the small block allocation table start block
    header_block_writer.setSBATStart(sbtw.getSBAT().getStartBlock());
    // set the small block allocation table block count
    header_block_writer.setSBATBlockCount(sbtw.getSBATBlockCount());
    // the header is now properly initialized. Make a list of
    // writers (the header block, followed by the documents, the
    // property table, the small block store, the small block
    // allocation table, the block allocation table, and the
    // extended block allocation table blocks)
    List<Object> writers = new ArrayList<Object>();
    writers.add(header_block_writer);
    writers.addAll(_documents);
    writers.add(_property_table);
    writers.add(sbtw);
    writers.add(sbtw.getSBAT());
    writers.add(bat);
    for (int j = 0; j < xbat_blocks.length; j++) {
        writers.add(xbat_blocks[j]);
    }
    // now, write everything out
    iter = writers.iterator();
    while (iter.hasNext()) {
        BlockWritable writer = (BlockWritable) iter.next();
        writer.writeBlocks(stream);
    }
}
Also used : BlockWritable(org.apache.poi.poifs.storage.BlockWritable) SmallBlockTableWriter(org.apache.poi.poifs.storage.SmallBlockTableWriter) HeaderBlockWriter(org.apache.poi.poifs.storage.HeaderBlockWriter) BATBlock(org.apache.poi.poifs.storage.BATBlock) ArrayList(java.util.ArrayList) BlockAllocationTableWriter(org.apache.poi.poifs.storage.BlockAllocationTableWriter)

Example 4 with BATBlock

use of org.apache.poi.poifs.storage.BATBlock in project poi by apache.

the class NPOIFSFileSystem method syncWithDataSource.

/**
     * Has our in-memory objects write their state
     *  to their backing blocks 
     */
private void syncWithDataSource() throws IOException {
    // Mini Stream + SBATs first, as mini-stream details have
    //  to be stored in the Root Property
    _mini_store.syncWithDataSource();
    // Properties
    NPOIFSStream propStream = new NPOIFSStream(this, _header.getPropertyStart());
    _property_table.preWrite();
    _property_table.write(propStream);
    // _header.setPropertyStart has been updated on write ...
    // HeaderBlock
    HeaderBlockWriter hbw = new HeaderBlockWriter(_header);
    hbw.writeBlock(getBlockAt(-1));
    // BATs
    for (BATBlock bat : _bat_blocks) {
        ByteBuffer block = getBlockAt(bat.getOurBlockIndex());
        BlockAllocationTableWriter.writeBlock(bat, block);
    }
    // XBats
    for (BATBlock bat : _xbat_blocks) {
        ByteBuffer block = getBlockAt(bat.getOurBlockIndex());
        BlockAllocationTableWriter.writeBlock(bat, block);
    }
}
Also used : HeaderBlockWriter(org.apache.poi.poifs.storage.HeaderBlockWriter) BATBlock(org.apache.poi.poifs.storage.BATBlock) ByteBuffer(java.nio.ByteBuffer)

Example 5 with BATBlock

use of org.apache.poi.poifs.storage.BATBlock in project poi by apache.

the class NPOIFSFileSystem method readCoreContents.

/**
     * Read and process the PropertiesTable and the
     *  FAT / XFAT blocks, so that we're ready to
     *  work with the file
     */
private void readCoreContents() throws IOException {
    // Grab the block size
    bigBlockSize = _header.getBigBlockSize();
    // Each block should only ever be used by one of the
    //  FAT, XFAT or Property Table. Ensure it does
    ChainLoopDetector loopDetector = getChainLoopDetector();
    // Read the FAT blocks
    for (int fatAt : _header.getBATArray()) {
        readBAT(fatAt, loopDetector);
    }
    // Work out how many FAT blocks remain in the XFATs
    int remainingFATs = _header.getBATCount() - _header.getBATArray().length;
    // Now read the XFAT blocks, and the FATs within them
    BATBlock xfat;
    int nextAt = _header.getXBATIndex();
    for (int i = 0; i < _header.getXBATCount(); i++) {
        loopDetector.claim(nextAt);
        ByteBuffer fatData = getBlockAt(nextAt);
        xfat = BATBlock.createBATBlock(bigBlockSize, fatData);
        xfat.setOurBlockIndex(nextAt);
        nextAt = xfat.getValueAt(bigBlockSize.getXBATEntriesPerBlock());
        _xbat_blocks.add(xfat);
        // Process all the (used) FATs from this XFAT
        int xbatFATs = Math.min(remainingFATs, bigBlockSize.getXBATEntriesPerBlock());
        for (int j = 0; j < xbatFATs; j++) {
            int fatAt = xfat.getValueAt(j);
            if (fatAt == POIFSConstants.UNUSED_BLOCK || fatAt == POIFSConstants.END_OF_CHAIN)
                break;
            readBAT(fatAt, loopDetector);
        }
        remainingFATs -= xbatFATs;
    }
    // We're now able to load steams
    // Use this to read in the properties
    _property_table = new NPropertyTable(_header, this);
    // Finally read the Small Stream FAT (SBAT) blocks
    BATBlock sfat;
    List<BATBlock> sbats = new ArrayList<BATBlock>();
    _mini_store = new NPOIFSMiniStore(this, _property_table.getRoot(), sbats, _header);
    nextAt = _header.getSBATStart();
    for (int i = 0; i < _header.getSBATCount() && nextAt != POIFSConstants.END_OF_CHAIN; i++) {
        loopDetector.claim(nextAt);
        ByteBuffer fatData = getBlockAt(nextAt);
        sfat = BATBlock.createBATBlock(bigBlockSize, fatData);
        sfat.setOurBlockIndex(nextAt);
        sbats.add(sfat);
        nextAt = getNextBlock(nextAt);
    }
}
Also used : BATBlock(org.apache.poi.poifs.storage.BATBlock) NPropertyTable(org.apache.poi.poifs.property.NPropertyTable) ArrayList(java.util.ArrayList) ByteBuffer(java.nio.ByteBuffer)

Aggregations

BATBlock (org.apache.poi.poifs.storage.BATBlock)11 ByteBuffer (java.nio.ByteBuffer)7 ByteArrayInputStream (java.io.ByteArrayInputStream)2 ArrayList (java.util.ArrayList)2 HeaderBlockWriter (org.apache.poi.poifs.storage.HeaderBlockWriter)2 ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 InputStream (java.io.InputStream)1 NPropertyTable (org.apache.poi.poifs.property.NPropertyTable)1 BlockAllocationTableReader (org.apache.poi.poifs.storage.BlockAllocationTableReader)1 BlockAllocationTableWriter (org.apache.poi.poifs.storage.BlockAllocationTableWriter)1 BlockWritable (org.apache.poi.poifs.storage.BlockWritable)1 HeaderBlock (org.apache.poi.poifs.storage.HeaderBlock)1 RawDataBlockList (org.apache.poi.poifs.storage.RawDataBlockList)1 SmallBlockTableWriter (org.apache.poi.poifs.storage.SmallBlockTableWriter)1