mirror of https://github.com/apache/poi.git
#64350 - Sonar fix - "Iterator.next()" methods should throw "NoSuchElementException"
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1876525 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
fde6f81305
commit
d06de78703
|
@ -18,6 +18,7 @@
|
||||||
package org.apache.poi.hssf.record.aggregates;
|
package org.apache.poi.hssf.record.aggregates;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import org.apache.poi.hssf.model.RecordStream;
|
import org.apache.poi.hssf.model.RecordStream;
|
||||||
import org.apache.poi.hssf.record.BlankRecord;
|
import org.apache.poi.hssf.record.BlankRecord;
|
||||||
|
@ -338,8 +339,9 @@ public final class ValueRecordsAggregate implements Iterable<CellValueRecordInte
|
||||||
}
|
}
|
||||||
|
|
||||||
public CellValueRecordInterface next() {
|
public CellValueRecordInterface next() {
|
||||||
if (!hasNext())
|
if (!hasNext()) {
|
||||||
throw new IndexOutOfBoundsException("iterator has no next");
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
|
||||||
curRowIndex = nextRowIndex;
|
curRowIndex = nextRowIndex;
|
||||||
curColIndex = nextColIndex;
|
curColIndex = nextColIndex;
|
||||||
|
|
|
@ -29,6 +29,7 @@ import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.poi.hpsf.ClassID;
|
import org.apache.poi.hpsf.ClassID;
|
||||||
|
@ -37,7 +38,7 @@ import org.apache.poi.hpsf.ClassID;
|
||||||
* A DirectoryEntry filter, which exposes another
|
* A DirectoryEntry filter, which exposes another
|
||||||
* DirectoryEntry less certain parts.
|
* DirectoryEntry less certain parts.
|
||||||
* This is typically used when copying or comparing
|
* This is typically used when copying or comparing
|
||||||
* Filesystems.
|
* Filesystems.
|
||||||
*/
|
*/
|
||||||
public class FilteringDirectoryNode implements DirectoryEntry
|
public class FilteringDirectoryNode implements DirectoryEntry
|
||||||
{
|
{
|
||||||
|
@ -49,14 +50,14 @@ public class FilteringDirectoryNode implements DirectoryEntry
|
||||||
* Excludes of our child directories
|
* Excludes of our child directories
|
||||||
*/
|
*/
|
||||||
private Map<String,List<String>> childExcludes;
|
private Map<String,List<String>> childExcludes;
|
||||||
|
|
||||||
private DirectoryEntry directory;
|
private DirectoryEntry directory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a filter round the specified directory, which
|
* Creates a filter round the specified directory, which
|
||||||
* will exclude entries such as "MyNode" and "MyDir/IgnoreNode".
|
* will exclude entries such as "MyNode" and "MyDir/IgnoreNode".
|
||||||
* The excludes can stretch into children, if they contain a /.
|
* The excludes can stretch into children, if they contain a /.
|
||||||
*
|
*
|
||||||
* @param directory The Directory to filter
|
* @param directory The Directory to filter
|
||||||
* @param excludes The Entries to exclude
|
* @param excludes The Entries to exclude
|
||||||
* @throws IllegalArgumentException if directory is null
|
* @throws IllegalArgumentException if directory is null
|
||||||
|
@ -66,7 +67,7 @@ public class FilteringDirectoryNode implements DirectoryEntry
|
||||||
throw new IllegalArgumentException("directory cannot be null");
|
throw new IllegalArgumentException("directory cannot be null");
|
||||||
}
|
}
|
||||||
this.directory = directory;
|
this.directory = directory;
|
||||||
|
|
||||||
// Process the excludes
|
// Process the excludes
|
||||||
this.excludes = new HashSet<>();
|
this.excludes = new HashSet<>();
|
||||||
this.childExcludes = new HashMap<>();
|
this.childExcludes = new HashMap<>();
|
||||||
|
@ -108,7 +109,7 @@ public class FilteringDirectoryNode implements DirectoryEntry
|
||||||
public Iterator<Entry> iterator() {
|
public Iterator<Entry> iterator() {
|
||||||
return getEntries();
|
return getEntries();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getEntryCount() {
|
public int getEntryCount() {
|
||||||
int size = directory.getEntryCount();
|
int size = directory.getEntryCount();
|
||||||
for (String excl : excludes) {
|
for (String excl : excludes) {
|
||||||
|
@ -118,7 +119,7 @@ public class FilteringDirectoryNode implements DirectoryEntry
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getEntryNames() {
|
public Set<String> getEntryNames() {
|
||||||
Set<String> names = new HashSet<>();
|
Set<String> names = new HashSet<>();
|
||||||
for (String name : directory.getEntryNames()) {
|
for (String name : directory.getEntryNames()) {
|
||||||
|
@ -144,7 +145,7 @@ public class FilteringDirectoryNode implements DirectoryEntry
|
||||||
if (excludes.contains(name)) {
|
if (excludes.contains(name)) {
|
||||||
throw new FileNotFoundException(name);
|
throw new FileNotFoundException(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Entry entry = directory.getEntry(name);
|
Entry entry = directory.getEntry(name);
|
||||||
return wrapEntry(entry);
|
return wrapEntry(entry);
|
||||||
}
|
}
|
||||||
|
@ -152,7 +153,7 @@ public class FilteringDirectoryNode implements DirectoryEntry
|
||||||
String name = entry.getName();
|
String name = entry.getName();
|
||||||
if (childExcludes.containsKey(name) && entry instanceof DirectoryEntry) {
|
if (childExcludes.containsKey(name) && entry instanceof DirectoryEntry) {
|
||||||
return new FilteringDirectoryNode(
|
return new FilteringDirectoryNode(
|
||||||
(DirectoryEntry)entry, childExcludes.get(name));
|
(DirectoryEntry)entry, childExcludes.get(name));
|
||||||
}
|
}
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
@ -172,7 +173,7 @@ public class FilteringDirectoryNode implements DirectoryEntry
|
||||||
public boolean renameTo(String newName) {
|
public boolean renameTo(String newName) {
|
||||||
return directory.renameTo(newName);
|
return directory.renameTo(newName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return directory.getName();
|
return directory.getName();
|
||||||
}
|
}
|
||||||
|
@ -188,11 +189,11 @@ public class FilteringDirectoryNode implements DirectoryEntry
|
||||||
public boolean isDocumentEntry() {
|
public boolean isDocumentEntry() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FilteringIterator implements Iterator<Entry> {
|
private class FilteringIterator implements Iterator<Entry> {
|
||||||
private Iterator<Entry> parent;
|
private Iterator<Entry> parent;
|
||||||
private Entry next;
|
private Entry next;
|
||||||
|
|
||||||
private FilteringIterator() {
|
private FilteringIterator() {
|
||||||
parent = directory.getEntries();
|
parent = directory.getEntries();
|
||||||
locateNext();
|
locateNext();
|
||||||
|
@ -207,17 +208,21 @@ public class FilteringDirectoryNode implements DirectoryEntry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
return (next != null);
|
return (next != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Entry next() {
|
public Entry next() {
|
||||||
|
if (!hasNext()) {
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
|
|
||||||
Entry e = next;
|
Entry e = next;
|
||||||
locateNext();
|
locateNext();
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove() {
|
public void remove() {
|
||||||
throw new UnsupportedOperationException("Remove not supported");
|
throw new UnsupportedOperationException("Remove not supported");
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import org.apache.poi.poifs.common.POIFSConstants;
|
import org.apache.poi.poifs.common.POIFSConstants;
|
||||||
import org.apache.poi.poifs.property.RootProperty;
|
import org.apache.poi.poifs.property.RootProperty;
|
||||||
|
@ -49,10 +50,10 @@ public class POIFSMiniStore extends BlockStore
|
||||||
this._sbat_blocks = sbats;
|
this._sbat_blocks = sbats;
|
||||||
this._header = header;
|
this._header = header;
|
||||||
this._root = root;
|
this._root = root;
|
||||||
|
|
||||||
this._mini_stream = new POIFSStream(filesystem, root.getStartBlock());
|
this._mini_stream = new POIFSStream(filesystem, root.getStartBlock());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the block at the given offset.
|
* Load the block at the given offset.
|
||||||
*/
|
*/
|
||||||
|
@ -61,18 +62,16 @@ public class POIFSMiniStore extends BlockStore
|
||||||
int byteOffset = offset * POIFSConstants.SMALL_BLOCK_SIZE;
|
int byteOffset = offset * POIFSConstants.SMALL_BLOCK_SIZE;
|
||||||
int bigBlockNumber = byteOffset / _filesystem.getBigBlockSize();
|
int bigBlockNumber = byteOffset / _filesystem.getBigBlockSize();
|
||||||
int bigBlockOffset = byteOffset % _filesystem.getBigBlockSize();
|
int bigBlockOffset = byteOffset % _filesystem.getBigBlockSize();
|
||||||
|
|
||||||
// Now locate the data block for it
|
// Now locate the data block for it
|
||||||
Iterator<ByteBuffer> it = _mini_stream.getBlockIterator();
|
Iterator<ByteBuffer> it = _mini_stream.getBlockIterator();
|
||||||
for(int i=0; i<bigBlockNumber; i++) {
|
for(int i=0; i<bigBlockNumber; i++) {
|
||||||
it.next();
|
it.next();
|
||||||
}
|
}
|
||||||
ByteBuffer dataBlock = it.next();
|
ByteBuffer dataBlock = it.next();
|
||||||
if(dataBlock == null) {
|
assert(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(
|
||||||
dataBlock.position() + bigBlockOffset
|
dataBlock.position() + bigBlockOffset
|
||||||
);
|
);
|
||||||
|
@ -80,7 +79,7 @@ public class POIFSMiniStore extends BlockStore
|
||||||
miniBuffer.limit(POIFSConstants.SMALL_BLOCK_SIZE);
|
miniBuffer.limit(POIFSConstants.SMALL_BLOCK_SIZE);
|
||||||
return miniBuffer;
|
return miniBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the block, extending the underlying stream if needed
|
* Load the block, extending the underlying stream if needed
|
||||||
*/
|
*/
|
||||||
|
@ -89,14 +88,14 @@ public class POIFSMiniStore extends BlockStore
|
||||||
if (_mini_stream.getStartBlock() == POIFSConstants.END_OF_CHAIN) {
|
if (_mini_stream.getStartBlock() == POIFSConstants.END_OF_CHAIN) {
|
||||||
firstInStore = true;
|
firstInStore = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to get it without extending the stream
|
// Try to get it without extending the stream
|
||||||
if (! firstInStore) {
|
if (! firstInStore) {
|
||||||
try {
|
try {
|
||||||
return getBlockAt(offset);
|
return getBlockAt(offset);
|
||||||
} catch(IndexOutOfBoundsException e) {}
|
} catch(NoSuchElementException e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Need to extend the stream
|
// Need to extend the stream
|
||||||
// TODO Replace this with proper append support
|
// TODO Replace this with proper append support
|
||||||
// For now, do the extending by hand...
|
// For now, do the extending by hand...
|
||||||
|
@ -104,7 +103,7 @@ public class POIFSMiniStore extends BlockStore
|
||||||
// Ask for another block
|
// Ask for another block
|
||||||
int newBigBlock = _filesystem.getFreeBlock();
|
int newBigBlock = _filesystem.getFreeBlock();
|
||||||
_filesystem.createBlockIfNeeded(newBigBlock);
|
_filesystem.createBlockIfNeeded(newBigBlock);
|
||||||
|
|
||||||
// If we are the first block to be allocated, initialise the stream
|
// If we are the first block to be allocated, initialise the stream
|
||||||
if (firstInStore) {
|
if (firstInStore) {
|
||||||
_filesystem._get_property_table().getRoot().setStartBlock(newBigBlock);
|
_filesystem._get_property_table().getRoot().setStartBlock(newBigBlock);
|
||||||
|
@ -123,14 +122,14 @@ public class POIFSMiniStore extends BlockStore
|
||||||
}
|
}
|
||||||
_filesystem.setNextBlock(block, newBigBlock);
|
_filesystem.setNextBlock(block, newBigBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is now the new end
|
// This is now the new end
|
||||||
_filesystem.setNextBlock(newBigBlock, POIFSConstants.END_OF_CHAIN);
|
_filesystem.setNextBlock(newBigBlock, POIFSConstants.END_OF_CHAIN);
|
||||||
|
|
||||||
// Now try again, to get the real small block
|
// Now try again, to get the real small block
|
||||||
return createBlockIfNeeded(offset);
|
return createBlockIfNeeded(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the BATBlock that handles the specified offset,
|
* Returns the BATBlock that handles the specified offset,
|
||||||
* and the relative index within it
|
* and the relative index within it
|
||||||
|
@ -140,7 +139,7 @@ public class POIFSMiniStore extends BlockStore
|
||||||
offset, _header, _sbat_blocks
|
offset, _header, _sbat_blocks
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Works out what block follows the specified one.
|
* Works out what block follows the specified one.
|
||||||
*/
|
*/
|
||||||
|
@ -148,7 +147,7 @@ public class POIFSMiniStore extends BlockStore
|
||||||
BATBlockAndIndex bai = getBATBlockAndIndex(offset);
|
BATBlockAndIndex bai = getBATBlockAndIndex(offset);
|
||||||
return bai.getBlock().getValueAt( bai.getIndex() );
|
return bai.getBlock().getValueAt( bai.getIndex() );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the record of what block follows the specified one.
|
* Changes the record of what block follows the specified one.
|
||||||
*/
|
*/
|
||||||
|
@ -158,7 +157,7 @@ public class POIFSMiniStore extends BlockStore
|
||||||
bai.getIndex(), nextBlock
|
bai.getIndex(), nextBlock
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds a free block, and returns its offset.
|
* Finds a free block, and returns its offset.
|
||||||
* This method will extend the file if needed, and if doing
|
* This method will extend the file if needed, and if doing
|
||||||
|
@ -166,7 +165,7 @@ public class POIFSMiniStore extends BlockStore
|
||||||
*/
|
*/
|
||||||
protected int getFreeBlock() throws IOException {
|
protected int getFreeBlock() throws IOException {
|
||||||
int sectorsPerSBAT = _filesystem.getBigBlockSizeDetails().getBATEntriesPerBlock();
|
int sectorsPerSBAT = _filesystem.getBigBlockSizeDetails().getBATEntriesPerBlock();
|
||||||
|
|
||||||
// First up, do we have any spare ones?
|
// First up, do we have any spare ones?
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
for (BATBlock sbat : _sbat_blocks) {
|
for (BATBlock sbat : _sbat_blocks) {
|
||||||
|
@ -185,16 +184,16 @@ public class POIFSMiniStore extends BlockStore
|
||||||
// Move onto the next SBAT
|
// Move onto the next SBAT
|
||||||
offset += sectorsPerSBAT;
|
offset += sectorsPerSBAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we get here, then there aren't any
|
// If we get here, then there aren't any
|
||||||
// free sectors in any of the SBATs
|
// free sectors in any of the SBATs
|
||||||
// So, we need to extend the chain and add another
|
// So, we need to extend the chain and add another
|
||||||
|
|
||||||
// Create a new BATBlock
|
// Create a new BATBlock
|
||||||
BATBlock newSBAT = BATBlock.createEmptyBATBlock(_filesystem.getBigBlockSizeDetails(), false);
|
BATBlock newSBAT = BATBlock.createEmptyBATBlock(_filesystem.getBigBlockSizeDetails(), false);
|
||||||
int batForSBAT = _filesystem.getFreeBlock();
|
int batForSBAT = _filesystem.getFreeBlock();
|
||||||
newSBAT.setOurBlockIndex(batForSBAT);
|
newSBAT.setOurBlockIndex(batForSBAT);
|
||||||
|
|
||||||
// Are we the first SBAT?
|
// Are we the first SBAT?
|
||||||
if(_header.getSBATCount() == 0) {
|
if(_header.getSBATCount() == 0) {
|
||||||
// Tell the header that we've got our first SBAT there
|
// Tell the header that we've got our first SBAT there
|
||||||
|
@ -212,24 +211,24 @@ public class POIFSMiniStore extends BlockStore
|
||||||
}
|
}
|
||||||
batOffset = nextBat;
|
batOffset = nextBat;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add it in at the end
|
// Add it in at the end
|
||||||
_filesystem.setNextBlock(batOffset, batForSBAT);
|
_filesystem.setNextBlock(batOffset, batForSBAT);
|
||||||
|
|
||||||
// And update the count
|
// And update the count
|
||||||
_header.setSBATBlockCount(
|
_header.setSBATBlockCount(
|
||||||
_header.getSBATCount() + 1
|
_header.getSBATCount() + 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finish allocating
|
// Finish allocating
|
||||||
_filesystem.setNextBlock(batForSBAT, POIFSConstants.END_OF_CHAIN);
|
_filesystem.setNextBlock(batForSBAT, POIFSConstants.END_OF_CHAIN);
|
||||||
_sbat_blocks.add(newSBAT);
|
_sbat_blocks.add(newSBAT);
|
||||||
|
|
||||||
// Return our first spot
|
// Return our first spot
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ChainLoopDetector getChainLoopDetector() {
|
protected ChainLoopDetector getChainLoopDetector() {
|
||||||
return new ChainLoopDetector( _root.getSize() );
|
return new ChainLoopDetector( _root.getSize() );
|
||||||
|
@ -238,7 +237,7 @@ public class POIFSMiniStore extends BlockStore
|
||||||
protected int getBlockStoreBlockSize() {
|
protected int getBlockStoreBlockSize() {
|
||||||
return POIFSConstants.SMALL_BLOCK_SIZE;
|
return POIFSConstants.SMALL_BLOCK_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes the SBATs to their backing blocks, and updates
|
* Writes the SBATs to their backing blocks, and updates
|
||||||
* the mini-stream size in the properties. Stream size is
|
* the mini-stream size in the properties. Stream size is
|
||||||
|
|
|
@ -23,6 +23,7 @@ import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import org.apache.poi.poifs.common.POIFSConstants;
|
import org.apache.poi.poifs.common.POIFSConstants;
|
||||||
import org.apache.poi.poifs.filesystem.BlockStore.ChainLoopDetector;
|
import org.apache.poi.poifs.filesystem.BlockStore.ChainLoopDetector;
|
||||||
|
@ -34,13 +35,13 @@ import org.apache.poi.poifs.storage.HeaderBlock;
|
||||||
* {@link POIFSFileSystem}. It can supply an iterator
|
* {@link POIFSFileSystem}. It can supply an iterator
|
||||||
* to read blocks, and way to write out to existing and
|
* to read blocks, and way to write out to existing and
|
||||||
* new blocks.
|
* new blocks.
|
||||||
* Most users will want a higher level version of this,
|
* Most users will want a higher level version of this,
|
||||||
* which deals with properties to track which stream
|
* which deals with properties to track which stream
|
||||||
* this is.
|
* this is.
|
||||||
* This only works on big block streams, it doesn't
|
* This only works on big block streams, it doesn't
|
||||||
* handle small block ones.
|
* handle small block ones.
|
||||||
* This uses the new NIO code
|
* This uses the new NIO code
|
||||||
*
|
*
|
||||||
* TODO Implement a streaming write method, and append
|
* TODO Implement a streaming write method, and append
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -49,17 +50,17 @@ public class POIFSStream implements Iterable<ByteBuffer>
|
||||||
private BlockStore blockStore;
|
private BlockStore blockStore;
|
||||||
private int startBlock;
|
private int startBlock;
|
||||||
private OutputStream outStream;
|
private OutputStream outStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for an existing stream. It's up to you
|
* Constructor for an existing stream. It's up to you
|
||||||
* to know how to get the start block (eg from a
|
* to know how to get the start block (eg from a
|
||||||
* {@link HeaderBlock} or a {@link Property})
|
* {@link HeaderBlock} or a {@link Property})
|
||||||
*/
|
*/
|
||||||
public POIFSStream(BlockStore blockStore, int startBlock) {
|
public POIFSStream(BlockStore blockStore, int startBlock) {
|
||||||
this.blockStore = blockStore;
|
this.blockStore = blockStore;
|
||||||
this.startBlock = startBlock;
|
this.startBlock = startBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for a new stream. A start block won't
|
* Constructor for a new stream. A start block won't
|
||||||
* be allocated until you begin writing to it.
|
* be allocated until you begin writing to it.
|
||||||
|
@ -68,7 +69,7 @@ public class POIFSStream implements Iterable<ByteBuffer>
|
||||||
this.blockStore = blockStore;
|
this.blockStore = blockStore;
|
||||||
this.startBlock = POIFSConstants.END_OF_CHAIN;
|
this.startBlock = POIFSConstants.END_OF_CHAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* What block does this stream start at?
|
* What block does this stream start at?
|
||||||
* Will be {@link POIFSConstants#END_OF_CHAIN} for a
|
* Will be {@link POIFSConstants#END_OF_CHAIN} for a
|
||||||
|
@ -85,7 +86,7 @@ public class POIFSStream implements Iterable<ByteBuffer>
|
||||||
public Iterator<ByteBuffer> iterator() {
|
public Iterator<ByteBuffer> iterator() {
|
||||||
return getBlockIterator();
|
return getBlockIterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator<ByteBuffer> getBlockIterator() {
|
Iterator<ByteBuffer> getBlockIterator() {
|
||||||
if(startBlock == POIFSConstants.END_OF_CHAIN) {
|
if(startBlock == POIFSConstants.END_OF_CHAIN) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
|
@ -113,11 +114,11 @@ public class POIFSStream implements Iterable<ByteBuffer>
|
||||||
}
|
}
|
||||||
return outStream;
|
return outStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Streaming write support
|
// TODO Streaming write support
|
||||||
// TODO then convert fixed sized write to use streaming internally
|
// TODO then convert fixed sized write to use streaming internally
|
||||||
// TODO Append write support (probably streaming)
|
// TODO Append write support (probably streaming)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frees all blocks in the stream
|
* Frees all blocks in the stream
|
||||||
*/
|
*/
|
||||||
|
@ -135,14 +136,14 @@ public class POIFSStream implements Iterable<ByteBuffer>
|
||||||
}
|
}
|
||||||
this.startBlock = POIFSConstants.END_OF_CHAIN;
|
this.startBlock = POIFSConstants.END_OF_CHAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class that handles a streaming read of one stream
|
* Class that handles a streaming read of one stream
|
||||||
*/
|
*/
|
||||||
protected class StreamBlockByteBufferIterator implements Iterator<ByteBuffer> {
|
protected class StreamBlockByteBufferIterator implements Iterator<ByteBuffer> {
|
||||||
private ChainLoopDetector loopDetector;
|
private ChainLoopDetector loopDetector;
|
||||||
private int nextBlock;
|
private int nextBlock;
|
||||||
|
|
||||||
StreamBlockByteBufferIterator(int firstBlock) {
|
StreamBlockByteBufferIterator(int firstBlock) {
|
||||||
this.nextBlock = firstBlock;
|
this.nextBlock = firstBlock;
|
||||||
try {
|
try {
|
||||||
|
@ -157,10 +158,10 @@ public class POIFSStream implements Iterable<ByteBuffer>
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer next() {
|
public ByteBuffer next() {
|
||||||
if(nextBlock == POIFSConstants.END_OF_CHAIN) {
|
if (!hasNext()) {
|
||||||
throw new IndexOutOfBoundsException("Can't read past the end of the stream");
|
throw new NoSuchElementException("Can't read past the end of the stream");
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
loopDetector.claim(nextBlock);
|
loopDetector.claim(nextBlock);
|
||||||
ByteBuffer data = blockStore.getBlockAt(nextBlock);
|
ByteBuffer data = blockStore.getBlockAt(nextBlock);
|
||||||
|
@ -175,7 +176,7 @@ public class POIFSStream implements Iterable<ByteBuffer>
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class StreamBlockByteBuffer extends OutputStream {
|
protected class StreamBlockByteBuffer extends OutputStream {
|
||||||
byte[] oneByte = new byte[1];
|
byte[] oneByte = new byte[1];
|
||||||
ByteBuffer buffer;
|
ByteBuffer buffer;
|
||||||
|
@ -192,25 +193,25 @@ public class POIFSStream implements Iterable<ByteBuffer>
|
||||||
|
|
||||||
void createBlockIfNeeded() throws IOException {
|
void createBlockIfNeeded() throws IOException {
|
||||||
if (buffer != null && buffer.hasRemaining()) return;
|
if (buffer != null && buffer.hasRemaining()) return;
|
||||||
|
|
||||||
int thisBlock = nextBlock;
|
int thisBlock = nextBlock;
|
||||||
|
|
||||||
// Allocate a block if needed, otherwise figure
|
// Allocate a block if needed, otherwise figure
|
||||||
// out what the next block will be
|
// out what the next block will be
|
||||||
if(thisBlock == POIFSConstants.END_OF_CHAIN) {
|
if(thisBlock == POIFSConstants.END_OF_CHAIN) {
|
||||||
thisBlock = blockStore.getFreeBlock();
|
thisBlock = blockStore.getFreeBlock();
|
||||||
loopDetector.claim(thisBlock);
|
loopDetector.claim(thisBlock);
|
||||||
|
|
||||||
// We're on the end of the chain
|
// We're on the end of the chain
|
||||||
nextBlock = POIFSConstants.END_OF_CHAIN;
|
nextBlock = POIFSConstants.END_OF_CHAIN;
|
||||||
|
|
||||||
// Mark the previous block as carrying on to us if needed
|
// Mark the previous block as carrying on to us if needed
|
||||||
if(prevBlock != POIFSConstants.END_OF_CHAIN) {
|
if(prevBlock != POIFSConstants.END_OF_CHAIN) {
|
||||||
blockStore.setNextBlock(prevBlock, thisBlock);
|
blockStore.setNextBlock(prevBlock, thisBlock);
|
||||||
}
|
}
|
||||||
blockStore.setNextBlock(thisBlock, POIFSConstants.END_OF_CHAIN);
|
blockStore.setNextBlock(thisBlock, POIFSConstants.END_OF_CHAIN);
|
||||||
|
|
||||||
// If we've just written the first block on a
|
// If we've just written the first block on a
|
||||||
// new stream, save the start block offset
|
// new stream, save the start block offset
|
||||||
if(startBlock == POIFSConstants.END_OF_CHAIN) {
|
if(startBlock == POIFSConstants.END_OF_CHAIN) {
|
||||||
startBlock = thisBlock;
|
startBlock = thisBlock;
|
||||||
|
@ -221,7 +222,7 @@ public class POIFSStream implements Iterable<ByteBuffer>
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer = blockStore.createBlockIfNeeded(thisBlock);
|
buffer = blockStore.createBlockIfNeeded(thisBlock);
|
||||||
|
|
||||||
// Update pointers
|
// Update pointers
|
||||||
prevBlock = thisBlock;
|
prevBlock = thisBlock;
|
||||||
}
|
}
|
||||||
|
@ -249,12 +250,12 @@ public class POIFSStream implements Iterable<ByteBuffer>
|
||||||
len -= writeBytes;
|
len -= writeBytes;
|
||||||
} while (len > 0);
|
} while (len > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
// If we're overwriting, free any remaining blocks
|
// If we're overwriting, free any remaining blocks
|
||||||
POIFSStream toFree = new POIFSStream(blockStore, nextBlock);
|
POIFSStream toFree = new POIFSStream(blockStore, nextBlock);
|
||||||
toFree.free(loopDetector);
|
toFree.free(loopDetector);
|
||||||
|
|
||||||
// Mark the end of the stream, if we have any data
|
// Mark the end of the stream, if we have any data
|
||||||
if (prevBlock != POIFSConstants.END_OF_CHAIN) {
|
if (prevBlock != POIFSConstants.END_OF_CHAIN) {
|
||||||
blockStore.setNextBlock(prevBlock, POIFSConstants.END_OF_CHAIN);
|
blockStore.setNextBlock(prevBlock, POIFSConstants.END_OF_CHAIN);
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
package org.apache.poi.util;
|
package org.apache.poi.util;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
// based on https://gist.github.com/EmmanuelOga/48df70b27ead4d80234b
|
// based on https://gist.github.com/EmmanuelOga/48df70b27ead4d80234b
|
||||||
@Internal
|
@Internal
|
||||||
|
@ -37,6 +38,9 @@ public class StringCodepointsIterable implements Iterable<String> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String next() {
|
public String next() {
|
||||||
|
if (!hasNext()) {
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
int codePoint = StringCodepointsIterable.this.string.codePointAt(index);
|
int codePoint = StringCodepointsIterable.this.string.codePointAt(index);
|
||||||
index += Character.charCount(codePoint);
|
index += Character.charCount(codePoint);
|
||||||
return new String(Character.toChars(codePoint));
|
return new String(Character.toChars(codePoint));
|
||||||
|
|
|
@ -17,9 +17,10 @@
|
||||||
|
|
||||||
package org.apache.poi.util;
|
package org.apache.poi.util;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.ISO_8859_1;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,7 +28,6 @@ import java.util.Locale;
|
||||||
*/
|
*/
|
||||||
@Internal
|
@Internal
|
||||||
public final class StringUtil {
|
public final class StringUtil {
|
||||||
private static final Charset ISO_8859_1 = StandardCharsets.ISO_8859_1;
|
|
||||||
//arbitrarily selected; may need to increase
|
//arbitrarily selected; may need to increase
|
||||||
private static final int MAX_RECORD_LENGTH = 10000000;
|
private static final int MAX_RECORD_LENGTH = 10000000;
|
||||||
|
|
||||||
|
@ -305,38 +305,6 @@ public final class StringUtil {
|
||||||
return haystack.regionMatches(true, start, suffix, 0, length);
|
return haystack.regionMatches(true, start, suffix, 0, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* An Iterator over an array of Strings.
|
|
||||||
*/
|
|
||||||
public static class StringsIterator implements Iterator<String> {
|
|
||||||
private String[] strings = {};
|
|
||||||
private int position;
|
|
||||||
|
|
||||||
public StringsIterator(String[] strings) {
|
|
||||||
if (strings != null) {
|
|
||||||
this.strings = strings.clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
return position < strings.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String next() {
|
|
||||||
int ourPos = position++;
|
|
||||||
if (ourPos >= strings.length) {
|
|
||||||
throw new ArrayIndexOutOfBoundsException(ourPos);
|
|
||||||
}
|
|
||||||
return strings[ourPos];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void remove() {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Internal
|
@Internal
|
||||||
public static String toLowerCase(char c) {
|
public static String toLowerCase(char c) {
|
||||||
return Character.toString(c).toLowerCase(Locale.ROOT);
|
return Character.toString(c).toLowerCase(Locale.ROOT);
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.apache.poi.common.usermodel.GenericRecord;
|
import org.apache.poi.common.usermodel.GenericRecord;
|
||||||
|
@ -172,6 +173,9 @@ public class HemfComment {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EmfCommentData next() {
|
public EmfCommentData next() {
|
||||||
|
if (!hasNext()) {
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
EmfCommentData toReturn = currentRecord;
|
EmfCommentData toReturn = currentRecord;
|
||||||
final boolean isEOF = (limit == -1 || leis.getReadIndex() >= startIdx+limit);
|
final boolean isEOF = (limit == -1 || leis.getReadIndex() >= startIdx+limit);
|
||||||
// (currentRecord instanceof HemfPlusMisc.EmfEof)
|
// (currentRecord instanceof HemfPlusMisc.EmfEof)
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.apache.poi.hemf.record.emf;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import org.apache.poi.util.LittleEndianConsts;
|
import org.apache.poi.util.LittleEndianConsts;
|
||||||
import org.apache.poi.util.LittleEndianInputStream;
|
import org.apache.poi.util.LittleEndianInputStream;
|
||||||
|
@ -44,6 +45,9 @@ public class HemfRecordIterator implements Iterator<HemfRecord> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HemfRecord next() {
|
public HemfRecord next() {
|
||||||
|
if (!hasNext()) {
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
HemfRecord toReturn = currentRecord;
|
HemfRecord toReturn = currentRecord;
|
||||||
currentRecord = (currentRecord instanceof HemfMisc.EmfEof) ? null : _next();
|
currentRecord = (currentRecord instanceof HemfMisc.EmfEof) ? null : _next();
|
||||||
return toReturn;
|
return toReturn;
|
||||||
|
|
|
@ -19,6 +19,7 @@ package org.apache.poi.hemf.record.emfplus;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import org.apache.poi.util.LittleEndianInputStream;
|
import org.apache.poi.util.LittleEndianInputStream;
|
||||||
import org.apache.poi.util.RecordFormatException;
|
import org.apache.poi.util.RecordFormatException;
|
||||||
|
@ -49,6 +50,9 @@ public class HemfPlusRecordIterator implements Iterator<HemfPlusRecord> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HemfPlusRecord next() {
|
public HemfPlusRecord next() {
|
||||||
|
if (!hasNext()) {
|
||||||
|
throw new NoSuchElementException();
|
||||||
|
}
|
||||||
HemfPlusRecord toReturn = currentRecord;
|
HemfPlusRecord toReturn = currentRecord;
|
||||||
// add the size for recordId/flags/recordSize/dataSize = 12 bytes
|
// add the size for recordId/flags/recordSize/dataSize = 12 bytes
|
||||||
final boolean isEOF = (limit == -1 || (leis.getReadIndex()-startIdx)+12 > limit);
|
final boolean isEOF = (limit == -1 || (leis.getReadIndex()-startIdx)+12 > limit);
|
||||||
|
|
|
@ -16,6 +16,17 @@
|
||||||
==================================================================== */
|
==================================================================== */
|
||||||
package org.apache.poi.hsmf.extractor;
|
package org.apache.poi.hsmf.extractor;
|
||||||
|
|
||||||
|
import static org.apache.poi.util.StringUtil.startsWithIgnoreCase;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.apache.poi.extractor.POIOLE2TextExtractor;
|
import org.apache.poi.extractor.POIOLE2TextExtractor;
|
||||||
import org.apache.poi.hsmf.MAPIMessage;
|
import org.apache.poi.hsmf.MAPIMessage;
|
||||||
import org.apache.poi.hsmf.datatypes.AttachmentChunks;
|
import org.apache.poi.hsmf.datatypes.AttachmentChunks;
|
||||||
|
@ -24,16 +35,6 @@ import org.apache.poi.hsmf.exceptions.ChunkNotFoundException;
|
||||||
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
import org.apache.poi.poifs.filesystem.DirectoryNode;
|
||||||
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
|
||||||
import org.apache.poi.util.LocaleUtil;
|
import org.apache.poi.util.LocaleUtil;
|
||||||
import org.apache.poi.util.Removal;
|
|
||||||
import org.apache.poi.util.StringUtil.StringsIterator;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import static org.apache.poi.util.StringUtil.startsWithIgnoreCase;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A text extractor for HSMF (Outlook) .msg files.
|
* A text extractor for HSMF (Outlook) .msg files.
|
||||||
|
@ -90,13 +91,11 @@ public class OutlookTextExtractor extends POIOLE2TextExtractor {
|
||||||
msg.guess7BitEncoding();
|
msg.guess7BitEncoding();
|
||||||
|
|
||||||
// Off we go
|
// Off we go
|
||||||
StringsIterator emails;
|
Iterator<String> emails;
|
||||||
try {
|
try {
|
||||||
emails = new StringsIterator(
|
emails = Arrays.asList(msg.getRecipientEmailAddressList()).iterator();
|
||||||
msg.getRecipientEmailAddressList()
|
|
||||||
);
|
|
||||||
} catch (ChunkNotFoundException e) {
|
} catch (ChunkNotFoundException e) {
|
||||||
emails = new StringsIterator(new String[0]);
|
emails = Collections.emptyIterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -174,7 +173,7 @@ public class OutlookTextExtractor extends POIOLE2TextExtractor {
|
||||||
* of emails, and does its best to return something like
|
* of emails, and does its best to return something like
|
||||||
* "Nick <nick@example.com>; Jim <jim@example.com>"
|
* "Nick <nick@example.com>; Jim <jim@example.com>"
|
||||||
*/
|
*/
|
||||||
protected void handleEmails(StringBuilder s, String type, String displayText, StringsIterator emails) {
|
protected void handleEmails(StringBuilder s, String type, String displayText, Iterator<String> emails) {
|
||||||
if (displayText == null || displayText.length() == 0) {
|
if (displayText == null || displayText.length() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,18 +18,23 @@
|
||||||
|
|
||||||
package org.apache.poi.poifs.filesystem;
|
package org.apache.poi.poifs.filesystem;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to test FilteringDirectoryNode functionality
|
* Class to test FilteringDirectoryNode functionality
|
||||||
*/
|
*/
|
||||||
|
@ -68,16 +73,20 @@ public final class TestFilteringDirectoryNode {
|
||||||
assertFalse(d.getEntry(eRoot.getName()).isDirectoryEntry());
|
assertFalse(d.getEntry(eRoot.getName()).isDirectoryEntry());
|
||||||
assertTrue(d.getEntry(eRoot.getName()).isDocumentEntry());
|
assertTrue(d.getEntry(eRoot.getName()).isDocumentEntry());
|
||||||
|
|
||||||
Iterator<Entry> i = d.getEntries();
|
Iterator<Entry> i = d.getEntries();
|
||||||
assertEquals(dirA, i.next());
|
assertEquals(dirA, i.next());
|
||||||
assertEquals(dirB, i.next());
|
assertEquals(dirB, i.next());
|
||||||
assertEquals(eRoot, i.next());
|
assertEquals(eRoot, i.next());
|
||||||
assertNull(i.next());
|
try {
|
||||||
|
assertNull(i.next());
|
||||||
|
fail("Should throw NoSuchElementException when depleted");
|
||||||
|
} catch (NoSuchElementException ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testChildFiltering() throws Exception {
|
public void testChildFiltering() throws Exception {
|
||||||
List<String> excl = Arrays.asList(new String[]{"NotThere", "AlsoNotThere", eRoot.getName()});
|
List<String> excl = Arrays.asList("NotThere", "AlsoNotThere", eRoot.getName());
|
||||||
FilteringDirectoryNode d = new FilteringDirectoryNode(fs.getRoot(), excl);
|
FilteringDirectoryNode d = new FilteringDirectoryNode(fs.getRoot(), excl);
|
||||||
|
|
||||||
assertEquals(2, d.getEntryCount());
|
assertEquals(2, d.getEntryCount());
|
||||||
|
@ -96,11 +105,15 @@ public final class TestFilteringDirectoryNode {
|
||||||
Iterator<Entry> i = d.getEntries();
|
Iterator<Entry> i = d.getEntries();
|
||||||
assertEquals(dirA, i.next());
|
assertEquals(dirA, i.next());
|
||||||
assertEquals(dirB, i.next());
|
assertEquals(dirB, i.next());
|
||||||
assertNull(i.next());
|
try {
|
||||||
|
assertNull(i.next());
|
||||||
|
fail("Should throw NoSuchElementException when depleted");
|
||||||
|
} catch (NoSuchElementException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Filter more
|
// Filter more
|
||||||
excl = Arrays.asList(new String[]{"NotThere", "AlsoNotThere", eRoot.getName(), dirA.getName()});
|
excl = Arrays.asList("NotThere", "AlsoNotThere", eRoot.getName(), dirA.getName());
|
||||||
d = new FilteringDirectoryNode(fs.getRoot(), excl);
|
d = new FilteringDirectoryNode(fs.getRoot(), excl);
|
||||||
|
|
||||||
assertEquals(1, d.getEntryCount());
|
assertEquals(1, d.getEntryCount());
|
||||||
|
@ -122,11 +135,15 @@ public final class TestFilteringDirectoryNode {
|
||||||
|
|
||||||
i = d.getEntries();
|
i = d.getEntries();
|
||||||
assertEquals(dirB, i.next());
|
assertEquals(dirB, i.next());
|
||||||
assertNull(i.next());
|
try {
|
||||||
|
assertNull(i.next());
|
||||||
|
fail("Should throw NoSuchElementException when depleted");
|
||||||
|
} catch (NoSuchElementException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Filter everything
|
// Filter everything
|
||||||
excl = Arrays.asList(new String[]{"NotThere", eRoot.getName(), dirA.getName(), dirB.getName()});
|
excl = Arrays.asList("NotThere", eRoot.getName(), dirA.getName(), dirB.getName());
|
||||||
d = new FilteringDirectoryNode(fs.getRoot(), excl);
|
d = new FilteringDirectoryNode(fs.getRoot(), excl);
|
||||||
|
|
||||||
assertEquals(0, d.getEntryCount());
|
assertEquals(0, d.getEntryCount());
|
||||||
|
@ -151,17 +168,19 @@ public final class TestFilteringDirectoryNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
i = d.getEntries();
|
i = d.getEntries();
|
||||||
assertNull(i.next());
|
try {
|
||||||
|
assertNull(i.next());
|
||||||
|
fail("Should throw NoSuchElementException when depleted");
|
||||||
|
} catch (NoSuchElementException ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNestedFiltering() throws Exception {
|
public void testNestedFiltering() throws Exception {
|
||||||
List<String> excl = Arrays.asList(new String[]{
|
List<String> excl = Arrays.asList(dirA.getName() + "/" + "MadeUp",
|
||||||
dirA.getName() + "/" + "MadeUp",
|
dirA.getName() + "/" + eA.getName(),
|
||||||
dirA.getName() + "/" + eA.getName(),
|
dirA.getName() + "/" + dirAA.getName() + "/Test",
|
||||||
dirA.getName() + "/" + dirAA.getName() + "/Test",
|
eRoot.getName());
|
||||||
eRoot.getName()
|
|
||||||
});
|
|
||||||
FilteringDirectoryNode d = new FilteringDirectoryNode(fs.getRoot(), excl);
|
FilteringDirectoryNode d = new FilteringDirectoryNode(fs.getRoot(), excl);
|
||||||
|
|
||||||
// Check main
|
// Check main
|
||||||
|
|
|
@ -26,6 +26,7 @@ import static org.junit.Assert.fail;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import org.apache.poi.POIDataSamples;
|
import org.apache.poi.POIDataSamples;
|
||||||
import org.apache.poi.poifs.common.POIFSConstants;
|
import org.apache.poi.poifs.common.POIFSConstants;
|
||||||
|
@ -38,7 +39,7 @@ import org.junit.Test;
|
||||||
@SuppressWarnings("CatchMayIgnoreException")
|
@SuppressWarnings("CatchMayIgnoreException")
|
||||||
public final class TestPOIFSMiniStore {
|
public final class TestPOIFSMiniStore {
|
||||||
private static final POIDataSamples _inst = POIDataSamples.getPOIFSInstance();
|
private static final POIDataSamples _inst = POIDataSamples.getPOIFSInstance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check that for a given mini block, we can correctly figure
|
* Check that for a given mini block, we can correctly figure
|
||||||
* out what the next one is
|
* out what the next one is
|
||||||
|
@ -52,24 +53,24 @@ public final class TestPOIFSMiniStore {
|
||||||
POIFSFileSystem fsD = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize4096.zvi"));
|
POIFSFileSystem fsD = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize4096.zvi"));
|
||||||
for(POIFSFileSystem fs : new POIFSFileSystem[] {fsA,fsB,fsC,fsD}) {
|
for(POIFSFileSystem fs : new POIFSFileSystem[] {fsA,fsB,fsC,fsD}) {
|
||||||
POIFSMiniStore ministore = fs.getMiniStore();
|
POIFSMiniStore ministore = fs.getMiniStore();
|
||||||
|
|
||||||
// 0 -> 51 is one stream
|
// 0 -> 51 is one stream
|
||||||
for(int i=0; i<50; i++) {
|
for(int i=0; i<50; i++) {
|
||||||
assertEquals(i+1, ministore.getNextBlock(i));
|
assertEquals(i+1, ministore.getNextBlock(i));
|
||||||
}
|
}
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(50));
|
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(50));
|
||||||
|
|
||||||
// 51 -> 103 is the next
|
// 51 -> 103 is the next
|
||||||
for(int i=51; i<103; i++) {
|
for(int i=51; i<103; i++) {
|
||||||
assertEquals(i+1, ministore.getNextBlock(i));
|
assertEquals(i+1, ministore.getNextBlock(i));
|
||||||
}
|
}
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(103));
|
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(103));
|
||||||
|
|
||||||
// Then there are 3 one block ones
|
// Then there are 3 one block ones
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(104));
|
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(104));
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(105));
|
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(105));
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(106));
|
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(106));
|
||||||
|
|
||||||
// 107 -> 154 is the next
|
// 107 -> 154 is the next
|
||||||
for(int i=107; i<154; i++) {
|
for(int i=107; i<154; i++) {
|
||||||
assertEquals(i+1, ministore.getNextBlock(i));
|
assertEquals(i+1, ministore.getNextBlock(i));
|
||||||
|
@ -81,32 +82,32 @@ public final class TestPOIFSMiniStore {
|
||||||
assertEquals(i+1, ministore.getNextBlock(i));
|
assertEquals(i+1, ministore.getNextBlock(i));
|
||||||
}
|
}
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(160));
|
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(160));
|
||||||
|
|
||||||
// 161 -> 166 is the next
|
// 161 -> 166 is the next
|
||||||
for(int i=161; i<166; i++) {
|
for(int i=161; i<166; i++) {
|
||||||
assertEquals(i+1, ministore.getNextBlock(i));
|
assertEquals(i+1, ministore.getNextBlock(i));
|
||||||
}
|
}
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(166));
|
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(166));
|
||||||
|
|
||||||
// 167 -> 172 is the next
|
// 167 -> 172 is the next
|
||||||
for(int i=167; i<172; i++) {
|
for(int i=167; i<172; i++) {
|
||||||
assertEquals(i+1, ministore.getNextBlock(i));
|
assertEquals(i+1, ministore.getNextBlock(i));
|
||||||
}
|
}
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(172));
|
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(172));
|
||||||
|
|
||||||
// Now some short ones
|
// Now some short ones
|
||||||
assertEquals(174 , ministore.getNextBlock(173));
|
assertEquals(174 , ministore.getNextBlock(173));
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(174));
|
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(174));
|
||||||
|
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(175));
|
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(175));
|
||||||
|
|
||||||
assertEquals(177 , ministore.getNextBlock(176));
|
assertEquals(177 , ministore.getNextBlock(176));
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(177));
|
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(177));
|
||||||
|
|
||||||
assertEquals(179 , ministore.getNextBlock(178));
|
assertEquals(179 , ministore.getNextBlock(178));
|
||||||
assertEquals(180 , ministore.getNextBlock(179));
|
assertEquals(180 , ministore.getNextBlock(179));
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(180));
|
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(180));
|
||||||
|
|
||||||
// 181 onwards is free
|
// 181 onwards is free
|
||||||
for(int i=181; i<fs.getBigBlockSizeDetails().getBATEntriesPerBlock(); i++) {
|
for(int i=181; i<fs.getBigBlockSizeDetails().getBATEntriesPerBlock(); i++) {
|
||||||
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(i));
|
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(i));
|
||||||
|
@ -131,11 +132,11 @@ public final class TestPOIFSMiniStore {
|
||||||
for(POIFSFileSystem fs : new POIFSFileSystem[] {fsA,fsB,fsC,fsD}) {
|
for(POIFSFileSystem fs : new POIFSFileSystem[] {fsA,fsB,fsC,fsD}) {
|
||||||
// Mini stream should be at big block zero
|
// Mini stream should be at big block zero
|
||||||
assertEquals(0, fs._get_property_table().getRoot().getStartBlock());
|
assertEquals(0, fs._get_property_table().getRoot().getStartBlock());
|
||||||
|
|
||||||
// Grab the ministore
|
// Grab the ministore
|
||||||
POIFSMiniStore ministore = fs.getMiniStore();
|
POIFSMiniStore ministore = fs.getMiniStore();
|
||||||
ByteBuffer b;
|
ByteBuffer b;
|
||||||
|
|
||||||
// Runs from the start of the data section in 64 byte chungs
|
// Runs from the start of the data section in 64 byte chungs
|
||||||
b = ministore.getBlockAt(0);
|
b = ministore.getBlockAt(0);
|
||||||
assertEquals((byte)0x9e, b.get());
|
assertEquals((byte)0x9e, b.get());
|
||||||
|
@ -146,7 +147,7 @@ public final class TestPOIFSMiniStore {
|
||||||
assertEquals((byte)0x21, b.get());
|
assertEquals((byte)0x21, b.get());
|
||||||
assertEquals((byte)0xd2, b.get());
|
assertEquals((byte)0xd2, b.get());
|
||||||
assertEquals((byte)0x11, b.get());
|
assertEquals((byte)0x11, b.get());
|
||||||
|
|
||||||
// And the next block
|
// And the next block
|
||||||
b = ministore.getBlockAt(1);
|
b = ministore.getBlockAt(1);
|
||||||
assertEquals((byte)0x00, b.get());
|
assertEquals((byte)0x00, b.get());
|
||||||
|
@ -157,7 +158,7 @@ public final class TestPOIFSMiniStore {
|
||||||
assertEquals((byte)0x02, b.get());
|
assertEquals((byte)0x02, b.get());
|
||||||
assertEquals((byte)0x00, b.get());
|
assertEquals((byte)0x00, b.get());
|
||||||
assertEquals((byte)0x00, b.get());
|
assertEquals((byte)0x00, b.get());
|
||||||
|
|
||||||
// Check the last data block
|
// Check the last data block
|
||||||
b = ministore.getBlockAt(180);
|
b = ministore.getBlockAt(180);
|
||||||
assertEquals((byte)0x30, b.get());
|
assertEquals((byte)0x30, b.get());
|
||||||
|
@ -168,7 +169,7 @@ public final class TestPOIFSMiniStore {
|
||||||
assertEquals((byte)0x00, b.get());
|
assertEquals((byte)0x00, b.get());
|
||||||
assertEquals((byte)0x00, b.get());
|
assertEquals((byte)0x00, b.get());
|
||||||
assertEquals((byte)0x80, b.get());
|
assertEquals((byte)0x80, b.get());
|
||||||
|
|
||||||
// And the rest until the end of the big block is zeros
|
// And the rest until the end of the big block is zeros
|
||||||
for(int i=181; i<184; i++) {
|
for(int i=181; i<184; i++) {
|
||||||
b = ministore.getBlockAt(i);
|
b = ministore.getBlockAt(i);
|
||||||
|
@ -187,7 +188,7 @@ public final class TestPOIFSMiniStore {
|
||||||
fsB.close();
|
fsB.close();
|
||||||
fsA.close();
|
fsA.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ask for free blocks where there are some already
|
* Ask for free blocks where there are some already
|
||||||
* to be had from the SFAT
|
* to be had from the SFAT
|
||||||
|
@ -196,27 +197,27 @@ public final class TestPOIFSMiniStore {
|
||||||
public void testGetFreeBlockWithSpare() throws Exception {
|
public void testGetFreeBlockWithSpare() throws Exception {
|
||||||
POIFSFileSystem fs = new POIFSFileSystem(_inst.getFile("BlockSize512.zvi"));
|
POIFSFileSystem fs = new POIFSFileSystem(_inst.getFile("BlockSize512.zvi"));
|
||||||
POIFSMiniStore ministore = fs.getMiniStore();
|
POIFSMiniStore ministore = fs.getMiniStore();
|
||||||
|
|
||||||
// Our 2nd SBAT block has spares
|
// Our 2nd SBAT block has spares
|
||||||
assertFalse(ministore.getBATBlockAndIndex(0).getBlock().hasFreeSectors());
|
assertFalse(ministore.getBATBlockAndIndex(0).getBlock().hasFreeSectors());
|
||||||
assertTrue(ministore.getBATBlockAndIndex(128).getBlock().hasFreeSectors());
|
assertTrue(ministore.getBATBlockAndIndex(128).getBlock().hasFreeSectors());
|
||||||
|
|
||||||
// First free one at 181
|
// First free one at 181
|
||||||
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(181));
|
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(181));
|
||||||
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(182));
|
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(182));
|
||||||
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(183));
|
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(183));
|
||||||
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(184));
|
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(184));
|
||||||
|
|
||||||
// Ask, will get 181
|
// Ask, will get 181
|
||||||
assertEquals(181, ministore.getFreeBlock());
|
assertEquals(181, ministore.getFreeBlock());
|
||||||
|
|
||||||
// Ask again, will still get 181 as not written to
|
// Ask again, will still get 181 as not written to
|
||||||
assertEquals(181, ministore.getFreeBlock());
|
assertEquals(181, ministore.getFreeBlock());
|
||||||
|
|
||||||
// Allocate it, then ask again
|
// Allocate it, then ask again
|
||||||
ministore.setNextBlock(181, POIFSConstants.END_OF_CHAIN);
|
ministore.setNextBlock(181, POIFSConstants.END_OF_CHAIN);
|
||||||
assertEquals(182, ministore.getFreeBlock());
|
assertEquals(182, ministore.getFreeBlock());
|
||||||
|
|
||||||
fs.close();
|
fs.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,21 +229,21 @@ public final class TestPOIFSMiniStore {
|
||||||
public void testGetFreeBlockWithNoneSpare() throws Exception {
|
public void testGetFreeBlockWithNoneSpare() throws Exception {
|
||||||
POIFSFileSystem fs = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize512.zvi"));
|
POIFSFileSystem fs = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize512.zvi"));
|
||||||
POIFSMiniStore ministore = fs.getMiniStore();
|
POIFSMiniStore ministore = fs.getMiniStore();
|
||||||
|
|
||||||
// We've spare ones from 181 to 255
|
// We've spare ones from 181 to 255
|
||||||
for(int i=181; i<256; i++) {
|
for(int i=181; i<256; i++) {
|
||||||
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(i));
|
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check our SBAT free stuff is correct
|
// Check our SBAT free stuff is correct
|
||||||
assertFalse(ministore.getBATBlockAndIndex(0).getBlock().hasFreeSectors());
|
assertFalse(ministore.getBATBlockAndIndex(0).getBlock().hasFreeSectors());
|
||||||
assertTrue(ministore.getBATBlockAndIndex(128).getBlock().hasFreeSectors());
|
assertTrue(ministore.getBATBlockAndIndex(128).getBlock().hasFreeSectors());
|
||||||
|
|
||||||
// Allocate all the spare ones
|
// Allocate all the spare ones
|
||||||
for(int i=181; i<256; i++) {
|
for(int i=181; i<256; i++) {
|
||||||
ministore.setNextBlock(i, POIFSConstants.END_OF_CHAIN);
|
ministore.setNextBlock(i, POIFSConstants.END_OF_CHAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SBAT are now full, but there's only the two
|
// SBAT are now full, but there's only the two
|
||||||
assertFalse(ministore.getBATBlockAndIndex(0).getBlock().hasFreeSectors());
|
assertFalse(ministore.getBATBlockAndIndex(0).getBlock().hasFreeSectors());
|
||||||
assertFalse(ministore.getBATBlockAndIndex(128).getBlock().hasFreeSectors());
|
assertFalse(ministore.getBATBlockAndIndex(128).getBlock().hasFreeSectors());
|
||||||
|
@ -250,30 +251,30 @@ public final class TestPOIFSMiniStore {
|
||||||
assertFalse(ministore.getBATBlockAndIndex(256).getBlock().hasFreeSectors());
|
assertFalse(ministore.getBATBlockAndIndex(256).getBlock().hasFreeSectors());
|
||||||
fail("Should only be two SBATs");
|
fail("Should only be two SBATs");
|
||||||
} catch(IndexOutOfBoundsException e) {}
|
} catch(IndexOutOfBoundsException e) {}
|
||||||
|
|
||||||
// Now ask for a free one, will need to extend the SBAT chain
|
// Now ask for a free one, will need to extend the SBAT chain
|
||||||
assertEquals(256, ministore.getFreeBlock());
|
assertEquals(256, ministore.getFreeBlock());
|
||||||
|
|
||||||
assertFalse(ministore.getBATBlockAndIndex(0).getBlock().hasFreeSectors());
|
assertFalse(ministore.getBATBlockAndIndex(0).getBlock().hasFreeSectors());
|
||||||
assertFalse(ministore.getBATBlockAndIndex(128).getBlock().hasFreeSectors());
|
assertFalse(ministore.getBATBlockAndIndex(128).getBlock().hasFreeSectors());
|
||||||
assertTrue(ministore.getBATBlockAndIndex(256).getBlock().hasFreeSectors());
|
assertTrue(ministore.getBATBlockAndIndex(256).getBlock().hasFreeSectors());
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(254)); // 2nd SBAT
|
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(254)); // 2nd SBAT
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(255)); // 2nd SBAT
|
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(255)); // 2nd SBAT
|
||||||
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(256)); // 3rd SBAT
|
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(256)); // 3rd SBAT
|
||||||
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(257)); // 3rd SBAT
|
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(257)); // 3rd SBAT
|
||||||
|
|
||||||
fs.close();
|
fs.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test that we will extend the underlying chain of
|
* Test that we will extend the underlying chain of
|
||||||
* big blocks that make up the ministream as needed
|
* big blocks that make up the ministream as needed
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testCreateBlockIfNeeded() throws Exception {
|
public void testCreateBlockIfNeeded() throws Exception {
|
||||||
POIFSFileSystem fs = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize512.zvi"));
|
POIFSFileSystem fs = new POIFSFileSystem(_inst.openResourceAsStream("BlockSize512.zvi"));
|
||||||
POIFSMiniStore ministore = fs.getMiniStore();
|
POIFSMiniStore ministore = fs.getMiniStore();
|
||||||
|
|
||||||
// 178 -> 179 -> 180, 181+ is free
|
// 178 -> 179 -> 180, 181+ is free
|
||||||
assertEquals(179 , ministore.getNextBlock(178));
|
assertEquals(179 , ministore.getNextBlock(178));
|
||||||
assertEquals(180 , ministore.getNextBlock(179));
|
assertEquals(180 , ministore.getNextBlock(179));
|
||||||
|
@ -281,7 +282,7 @@ public final class TestPOIFSMiniStore {
|
||||||
for(int i=181; i<256; i++) {
|
for(int i=181; i<256; i++) {
|
||||||
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(i));
|
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
// However, the ministore data only covers blocks to 183
|
// However, the ministore data only covers blocks to 183
|
||||||
for(int i=0; i<=183; i++) {
|
for(int i=0; i<=183; i++) {
|
||||||
ministore.getBlockAt(i);
|
ministore.getBlockAt(i);
|
||||||
|
@ -289,8 +290,8 @@ public final class TestPOIFSMiniStore {
|
||||||
try {
|
try {
|
||||||
ministore.getBlockAt(184);
|
ministore.getBlockAt(184);
|
||||||
fail("No block at 184");
|
fail("No block at 184");
|
||||||
} catch(IndexOutOfBoundsException e) {}
|
} catch(NoSuchElementException e) {}
|
||||||
|
|
||||||
// The ministore itself is made up of 23 big blocks
|
// The ministore itself is made up of 23 big blocks
|
||||||
Iterator<ByteBuffer> it = new POIFSStream(fs, fs.getRoot().getProperty().getStartBlock()).getBlockIterator();
|
Iterator<ByteBuffer> it = new POIFSStream(fs, fs.getRoot().getProperty().getStartBlock()).getBlockIterator();
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
@ -299,10 +300,10 @@ public final class TestPOIFSMiniStore {
|
||||||
it.next();
|
it.next();
|
||||||
}
|
}
|
||||||
assertEquals(23, count);
|
assertEquals(23, count);
|
||||||
|
|
||||||
// Ask it to get block 184 with creating, it will do
|
// Ask it to get block 184 with creating, it will do
|
||||||
ministore.createBlockIfNeeded(184);
|
ministore.createBlockIfNeeded(184);
|
||||||
|
|
||||||
// The ministore should be one big block bigger now
|
// The ministore should be one big block bigger now
|
||||||
it = new POIFSStream(fs, fs.getRoot().getProperty().getStartBlock()).getBlockIterator();
|
it = new POIFSStream(fs, fs.getRoot().getProperty().getStartBlock()).getBlockIterator();
|
||||||
count = 0;
|
count = 0;
|
||||||
|
@ -311,7 +312,7 @@ public final class TestPOIFSMiniStore {
|
||||||
it.next();
|
it.next();
|
||||||
}
|
}
|
||||||
assertEquals(24, count);
|
assertEquals(24, count);
|
||||||
|
|
||||||
// The mini block block counts now run to 191
|
// The mini block block counts now run to 191
|
||||||
for(int i=0; i<=191; i++) {
|
for(int i=0; i<=191; i++) {
|
||||||
ministore.getBlockAt(i);
|
ministore.getBlockAt(i);
|
||||||
|
@ -319,14 +320,14 @@ public final class TestPOIFSMiniStore {
|
||||||
try {
|
try {
|
||||||
ministore.getBlockAt(192);
|
ministore.getBlockAt(192);
|
||||||
fail("No block at 192");
|
fail("No block at 192");
|
||||||
} catch(IndexOutOfBoundsException e) {}
|
} catch(NoSuchElementException e) {}
|
||||||
|
|
||||||
|
|
||||||
// Now try writing through to 192, check that the SBAT and blocks are there
|
// Now try writing through to 192, check that the SBAT and blocks are there
|
||||||
byte[] data = new byte[15*64];
|
byte[] data = new byte[15*64];
|
||||||
POIFSStream stream = new POIFSStream(ministore, 178);
|
POIFSStream stream = new POIFSStream(ministore, 178);
|
||||||
stream.updateContents(data);
|
stream.updateContents(data);
|
||||||
|
|
||||||
// Check now
|
// Check now
|
||||||
assertEquals(179 , ministore.getNextBlock(178));
|
assertEquals(179 , ministore.getNextBlock(178));
|
||||||
assertEquals(180 , ministore.getNextBlock(179));
|
assertEquals(180 , ministore.getNextBlock(179));
|
||||||
|
@ -346,10 +347,10 @@ public final class TestPOIFSMiniStore {
|
||||||
for(int i=193; i<256; i++) {
|
for(int i=193; i<256; i++) {
|
||||||
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(i));
|
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.close();
|
fs.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateMiniStoreFirst() throws Exception {
|
public void testCreateMiniStoreFirst() throws Exception {
|
||||||
POIFSFileSystem fs = new POIFSFileSystem();
|
POIFSFileSystem fs = new POIFSFileSystem();
|
||||||
|
@ -365,14 +366,14 @@ public final class TestPOIFSMiniStore {
|
||||||
try {
|
try {
|
||||||
ministore.getNextBlock(0);
|
ministore.getNextBlock(0);
|
||||||
} catch (IndexOutOfBoundsException e) {}
|
} catch (IndexOutOfBoundsException e) {}
|
||||||
|
|
||||||
// Write a very small new document, will populate the ministore for us
|
// Write a very small new document, will populate the ministore for us
|
||||||
byte[] data = new byte[8];
|
byte[] data = new byte[8];
|
||||||
for (int i=0; i<data.length; i++) {
|
for (int i=0; i<data.length; i++) {
|
||||||
data[i] = (byte)(i+42);
|
data[i] = (byte)(i+42);
|
||||||
}
|
}
|
||||||
fs.getRoot().createDocument("mini", new ByteArrayInputStream(data));
|
fs.getRoot().createDocument("mini", new ByteArrayInputStream(data));
|
||||||
|
|
||||||
// Should now have a mini-fat and a mini-stream
|
// Should now have a mini-fat and a mini-stream
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(0));
|
assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(0));
|
||||||
assertEquals(POIFSConstants.FAT_SECTOR_BLOCK,fs.getNextBlock(1));
|
assertEquals(POIFSConstants.FAT_SECTOR_BLOCK,fs.getNextBlock(1));
|
||||||
|
@ -381,11 +382,11 @@ public final class TestPOIFSMiniStore {
|
||||||
assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(4));
|
assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(4));
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(0));
|
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(0));
|
||||||
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(1));
|
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(1));
|
||||||
|
|
||||||
// Re-fetch the mini store, and add it a second time
|
// Re-fetch the mini store, and add it a second time
|
||||||
ministore = fs.getMiniStore();
|
ministore = fs.getMiniStore();
|
||||||
fs.getRoot().createDocument("mini2", new ByteArrayInputStream(data));
|
fs.getRoot().createDocument("mini2", new ByteArrayInputStream(data));
|
||||||
|
|
||||||
// Main unchanged, ministore has a second
|
// Main unchanged, ministore has a second
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(0));
|
assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(0));
|
||||||
assertEquals(POIFSConstants.FAT_SECTOR_BLOCK,fs.getNextBlock(1));
|
assertEquals(POIFSConstants.FAT_SECTOR_BLOCK,fs.getNextBlock(1));
|
||||||
|
@ -395,7 +396,7 @@ public final class TestPOIFSMiniStore {
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(0));
|
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(0));
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(1));
|
assertEquals(POIFSConstants.END_OF_CHAIN, ministore.getNextBlock(1));
|
||||||
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(2));
|
assertEquals(POIFSConstants.UNUSED_BLOCK, ministore.getNextBlock(2));
|
||||||
|
|
||||||
// Check the data is unchanged and the right length
|
// Check the data is unchanged and the right length
|
||||||
entry = (DocumentEntry)fs.getRoot().getEntry("mini");
|
entry = (DocumentEntry)fs.getRoot().getEntry("mini");
|
||||||
assertEquals(data.length, entry.getSize());
|
assertEquals(data.length, entry.getSize());
|
||||||
|
@ -404,7 +405,7 @@ public final class TestPOIFSMiniStore {
|
||||||
IOUtils.readFully(dis, rdata);
|
IOUtils.readFully(dis, rdata);
|
||||||
assertArrayEquals(data, rdata);
|
assertArrayEquals(data, rdata);
|
||||||
dis.close();
|
dis.close();
|
||||||
|
|
||||||
entry = (DocumentEntry)fs.getRoot().getEntry("mini2");
|
entry = (DocumentEntry)fs.getRoot().getEntry("mini2");
|
||||||
assertEquals(data.length, entry.getSize());
|
assertEquals(data.length, entry.getSize());
|
||||||
rdata = new byte[data.length];
|
rdata = new byte[data.length];
|
||||||
|
@ -416,7 +417,7 @@ public final class TestPOIFSMiniStore {
|
||||||
// Done
|
// Done
|
||||||
fs.close();
|
fs.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMultiBlockStream() throws Exception {
|
public void testMultiBlockStream() throws Exception {
|
||||||
byte[] data1B = new byte[63];
|
byte[] data1B = new byte[63];
|
||||||
|
@ -427,7 +428,7 @@ public final class TestPOIFSMiniStore {
|
||||||
for (int i=0; i<data2B.length; i++) {
|
for (int i=0; i<data2B.length; i++) {
|
||||||
data2B[i] = (byte)(i+4);
|
data2B[i] = (byte)(i+4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// New filesystem and store to use
|
// New filesystem and store to use
|
||||||
POIFSFileSystem fs = new POIFSFileSystem();
|
POIFSFileSystem fs = new POIFSFileSystem();
|
||||||
|
|
||||||
|
@ -435,41 +436,41 @@ public final class TestPOIFSMiniStore {
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(0));
|
assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(0));
|
||||||
assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(1));
|
assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(1));
|
||||||
assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(2));
|
assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(2));
|
||||||
|
|
||||||
// Store the 2 block one, should use 2 mini blocks, and request
|
// Store the 2 block one, should use 2 mini blocks, and request
|
||||||
// the use of 2 big blocks
|
// the use of 2 big blocks
|
||||||
POIFSMiniStore ministore = fs.getMiniStore();
|
POIFSMiniStore ministore = fs.getMiniStore();
|
||||||
fs.getRoot().createDocument("mini2", new ByteArrayInputStream(data2B));
|
fs.getRoot().createDocument("mini2", new ByteArrayInputStream(data2B));
|
||||||
|
|
||||||
// Check
|
// Check
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(0));
|
assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(0));
|
||||||
assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(1));
|
assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(1));
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(2)); // SBAT
|
assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(2)); // SBAT
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(3)); // Mini
|
assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(3)); // Mini
|
||||||
assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(4));
|
assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(4));
|
||||||
|
|
||||||
// First 2 Mini blocks will be used
|
// First 2 Mini blocks will be used
|
||||||
assertEquals(2, ministore.getFreeBlock());
|
assertEquals(2, ministore.getFreeBlock());
|
||||||
|
|
||||||
// Add one more mini-stream, and check
|
// Add one more mini-stream, and check
|
||||||
fs.getRoot().createDocument("mini1", new ByteArrayInputStream(data1B));
|
fs.getRoot().createDocument("mini1", new ByteArrayInputStream(data1B));
|
||||||
|
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(0));
|
assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(0));
|
||||||
assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(1));
|
assertEquals(POIFSConstants.FAT_SECTOR_BLOCK, fs.getNextBlock(1));
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(2)); // SBAT
|
assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(2)); // SBAT
|
||||||
assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(3)); // Mini
|
assertEquals(POIFSConstants.END_OF_CHAIN, fs.getNextBlock(3)); // Mini
|
||||||
assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(4));
|
assertEquals(POIFSConstants.UNUSED_BLOCK, fs.getNextBlock(4));
|
||||||
|
|
||||||
// One more mini-block will be used
|
// One more mini-block will be used
|
||||||
assertEquals(3, ministore.getFreeBlock());
|
assertEquals(3, ministore.getFreeBlock());
|
||||||
|
|
||||||
// Check the contents too
|
// Check the contents too
|
||||||
byte[] r1 = new byte[data1B.length];
|
byte[] r1 = new byte[data1B.length];
|
||||||
DocumentInputStream dis = fs.createDocumentInputStream("mini1");
|
DocumentInputStream dis = fs.createDocumentInputStream("mini1");
|
||||||
IOUtils.readFully(dis, r1);
|
IOUtils.readFully(dis, r1);
|
||||||
dis.close();
|
dis.close();
|
||||||
assertArrayEquals(data1B, r1);
|
assertArrayEquals(data1B, r1);
|
||||||
|
|
||||||
byte[] r2 = new byte[data2B.length];
|
byte[] r2 = new byte[data2B.length];
|
||||||
dis = fs.createDocumentInputStream("mini2");
|
dis = fs.createDocumentInputStream("mini2");
|
||||||
IOUtils.readFully(dis, r2);
|
IOUtils.readFully(dis, r2);
|
||||||
|
|
|
@ -36,6 +36,7 @@ import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import org.apache.poi.POIDataSamples;
|
import org.apache.poi.POIDataSamples;
|
||||||
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
import org.apache.poi.hpsf.DocumentSummaryInformation;
|
||||||
|
@ -72,12 +73,8 @@ public final class TestPOIFSStream {
|
||||||
POIFSStream stream = new POIFSStream(fs, 98);
|
POIFSStream stream = new POIFSStream(fs, 98);
|
||||||
Iterator<ByteBuffer> i = stream.getBlockIterator();
|
Iterator<ByteBuffer> i = stream.getBlockIterator();
|
||||||
assertTrue(i.hasNext());
|
assertTrue(i.hasNext());
|
||||||
assertTrue(i.hasNext());
|
|
||||||
assertTrue(i.hasNext());
|
|
||||||
ByteBuffer b = i.next();
|
ByteBuffer b = i.next();
|
||||||
assertFalse(i.hasNext());
|
assertFalse(i.hasNext());
|
||||||
assertFalse(i.hasNext());
|
|
||||||
assertFalse(i.hasNext());
|
|
||||||
|
|
||||||
// Check the contents
|
// Check the contents
|
||||||
assertEquals((byte)0x81, b.get());
|
assertEquals((byte)0x81, b.get());
|
||||||
|
@ -103,15 +100,10 @@ public final class TestPOIFSStream {
|
||||||
POIFSStream stream = new POIFSStream(fs, 97);
|
POIFSStream stream = new POIFSStream(fs, 97);
|
||||||
Iterator<ByteBuffer> i = stream.getBlockIterator();
|
Iterator<ByteBuffer> i = stream.getBlockIterator();
|
||||||
assertTrue(i.hasNext());
|
assertTrue(i.hasNext());
|
||||||
assertTrue(i.hasNext());
|
|
||||||
assertTrue(i.hasNext());
|
|
||||||
ByteBuffer b97 = i.next();
|
ByteBuffer b97 = i.next();
|
||||||
assertTrue(i.hasNext());
|
assertTrue(i.hasNext());
|
||||||
assertTrue(i.hasNext());
|
|
||||||
ByteBuffer b98 = i.next();
|
ByteBuffer b98 = i.next();
|
||||||
assertFalse(i.hasNext());
|
assertFalse(i.hasNext());
|
||||||
assertFalse(i.hasNext());
|
|
||||||
assertFalse(i.hasNext());
|
|
||||||
|
|
||||||
// Check the contents of the 1st block
|
// Check the contents of the 1st block
|
||||||
assertEquals((byte)0x01, b97.get());
|
assertEquals((byte)0x01, b97.get());
|
||||||
|
@ -169,18 +161,21 @@ public final class TestPOIFSStream {
|
||||||
|
|
||||||
// Check the contents
|
// Check the contents
|
||||||
// 1st block is at 0
|
// 1st block is at 0
|
||||||
|
assertNotNull(b0);
|
||||||
assertEquals((byte)0x9e, b0.get());
|
assertEquals((byte)0x9e, b0.get());
|
||||||
assertEquals((byte)0x75, b0.get());
|
assertEquals((byte)0x75, b0.get());
|
||||||
assertEquals((byte)0x97, b0.get());
|
assertEquals((byte)0x97, b0.get());
|
||||||
assertEquals((byte)0xf6, b0.get());
|
assertEquals((byte)0xf6, b0.get());
|
||||||
|
|
||||||
// 2nd block is at 1
|
// 2nd block is at 1
|
||||||
|
assertNotNull(b1);
|
||||||
assertEquals((byte)0x86, b1.get());
|
assertEquals((byte)0x86, b1.get());
|
||||||
assertEquals((byte)0x09, b1.get());
|
assertEquals((byte)0x09, b1.get());
|
||||||
assertEquals((byte)0x22, b1.get());
|
assertEquals((byte)0x22, b1.get());
|
||||||
assertEquals((byte)0xfb, b1.get());
|
assertEquals((byte)0xfb, b1.get());
|
||||||
|
|
||||||
// last block is at 89
|
// last block is at 89
|
||||||
|
assertNotNull(b22);
|
||||||
assertEquals((byte)0xfe, b22.get());
|
assertEquals((byte)0xfe, b22.get());
|
||||||
assertEquals((byte)0xff, b22.get());
|
assertEquals((byte)0xff, b22.get());
|
||||||
assertEquals((byte)0x00, b22.get());
|
assertEquals((byte)0x00, b22.get());
|
||||||
|
@ -204,18 +199,12 @@ public final class TestPOIFSStream {
|
||||||
POIFSStream stream = new POIFSStream(fs, 0);
|
POIFSStream stream = new POIFSStream(fs, 0);
|
||||||
Iterator<ByteBuffer> i = stream.getBlockIterator();
|
Iterator<ByteBuffer> i = stream.getBlockIterator();
|
||||||
assertTrue(i.hasNext());
|
assertTrue(i.hasNext());
|
||||||
assertTrue(i.hasNext());
|
|
||||||
assertTrue(i.hasNext());
|
|
||||||
ByteBuffer b0 = i.next();
|
ByteBuffer b0 = i.next();
|
||||||
assertTrue(i.hasNext());
|
assertTrue(i.hasNext());
|
||||||
assertTrue(i.hasNext());
|
|
||||||
ByteBuffer b1 = i.next();
|
ByteBuffer b1 = i.next();
|
||||||
assertTrue(i.hasNext());
|
assertTrue(i.hasNext());
|
||||||
assertTrue(i.hasNext());
|
|
||||||
ByteBuffer b2 = i.next();
|
ByteBuffer b2 = i.next();
|
||||||
assertFalse(i.hasNext());
|
assertFalse(i.hasNext());
|
||||||
assertFalse(i.hasNext());
|
|
||||||
assertFalse(i.hasNext());
|
|
||||||
|
|
||||||
// Check the contents of the 1st block
|
// Check the contents of the 1st block
|
||||||
assertEquals((byte)0x9E, b0.get());
|
assertEquals((byte)0x9E, b0.get());
|
||||||
|
@ -304,17 +293,12 @@ public final class TestPOIFSStream {
|
||||||
POIFSStream stream = new POIFSStream(ministore, 178);
|
POIFSStream stream = new POIFSStream(ministore, 178);
|
||||||
Iterator<ByteBuffer> i = stream.getBlockIterator();
|
Iterator<ByteBuffer> i = stream.getBlockIterator();
|
||||||
assertTrue(i.hasNext());
|
assertTrue(i.hasNext());
|
||||||
assertTrue(i.hasNext());
|
|
||||||
assertTrue(i.hasNext());
|
|
||||||
ByteBuffer b178 = i.next();
|
ByteBuffer b178 = i.next();
|
||||||
assertTrue(i.hasNext());
|
assertTrue(i.hasNext());
|
||||||
assertTrue(i.hasNext());
|
|
||||||
ByteBuffer b179 = i.next();
|
ByteBuffer b179 = i.next();
|
||||||
assertTrue(i.hasNext());
|
assertTrue(i.hasNext());
|
||||||
ByteBuffer b180 = i.next();
|
ByteBuffer b180 = i.next();
|
||||||
assertFalse(i.hasNext());
|
assertFalse(i.hasNext());
|
||||||
assertFalse(i.hasNext());
|
|
||||||
assertFalse(i.hasNext());
|
|
||||||
|
|
||||||
// Check the contents of the 1st block
|
// Check the contents of the 1st block
|
||||||
assertEquals((byte)0xfe, b178.get());
|
assertEquals((byte)0xfe, b178.get());
|
||||||
|
@ -803,7 +787,7 @@ public final class TestPOIFSStream {
|
||||||
try {
|
try {
|
||||||
ministore.getBlockAt(184);
|
ministore.getBlockAt(184);
|
||||||
fail("Block 184 should be off the end of the list");
|
fail("Block 184 should be off the end of the list");
|
||||||
} catch (IndexOutOfBoundsException e) {
|
} catch (NoSuchElementException e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
data = new byte[64 * 6 + 12];
|
data = new byte[64 * 6 + 12];
|
||||||
|
|
|
@ -24,7 +24,6 @@ import static org.junit.Assert.fail;
|
||||||
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
import org.apache.poi.util.StringUtil.StringsIterator;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -127,52 +126,6 @@ public class TestStringUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testStringsIterator() {
|
|
||||||
StringsIterator i;
|
|
||||||
|
|
||||||
|
|
||||||
i = new StringsIterator(new String[0]);
|
|
||||||
assertFalse(i.hasNext());
|
|
||||||
try {
|
|
||||||
i.next();
|
|
||||||
fail();
|
|
||||||
} catch(ArrayIndexOutOfBoundsException e) {
|
|
||||||
// expected here
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
i = new StringsIterator(new String[] {"1"});
|
|
||||||
assertTrue(i.hasNext());
|
|
||||||
assertEquals("1", i.next());
|
|
||||||
|
|
||||||
assertFalse(i.hasNext());
|
|
||||||
try {
|
|
||||||
i.next();
|
|
||||||
fail();
|
|
||||||
} catch(ArrayIndexOutOfBoundsException e) {
|
|
||||||
// expected here
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
i = new StringsIterator(new String[] {"1","2","3"});
|
|
||||||
assertTrue(i.hasNext());
|
|
||||||
assertEquals("1", i.next());
|
|
||||||
assertTrue(i.hasNext());
|
|
||||||
assertEquals("2", i.next());
|
|
||||||
assertTrue(i.hasNext());
|
|
||||||
assertEquals("3", i.next());
|
|
||||||
|
|
||||||
assertFalse(i.hasNext());
|
|
||||||
try {
|
|
||||||
i.next();
|
|
||||||
fail();
|
|
||||||
} catch(ArrayIndexOutOfBoundsException e) {
|
|
||||||
// expected here
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void startsWithIgnoreCase() {
|
public void startsWithIgnoreCase() {
|
||||||
assertTrue("same string", StringUtil.startsWithIgnoreCase("Apache POI", "Apache POI"));
|
assertTrue("same string", StringUtil.startsWithIgnoreCase("Apache POI", "Apache POI"));
|
||||||
|
@ -181,7 +134,7 @@ public class TestStringUtil {
|
||||||
assertFalse("leading whitespace should not be ignored", StringUtil.startsWithIgnoreCase(" Apache POI project", "Apache POI"));
|
assertFalse("leading whitespace should not be ignored", StringUtil.startsWithIgnoreCase(" Apache POI project", "Apache POI"));
|
||||||
assertFalse("shorter string", StringUtil.startsWithIgnoreCase("Apache", "Apache POI"));
|
assertFalse("shorter string", StringUtil.startsWithIgnoreCase("Apache", "Apache POI"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void endsWithIgnoreCase() {
|
public void endsWithIgnoreCase() {
|
||||||
assertTrue("same string", StringUtil.endsWithIgnoreCase("Apache POI", "Apache POI"));
|
assertTrue("same string", StringUtil.endsWithIgnoreCase("Apache POI", "Apache POI"));
|
||||||
|
@ -190,34 +143,34 @@ public class TestStringUtil {
|
||||||
assertFalse("trailing whitespace should not be ignored", StringUtil.endsWithIgnoreCase("Apache POI project ", "Apache POI"));
|
assertFalse("trailing whitespace should not be ignored", StringUtil.endsWithIgnoreCase("Apache POI project ", "Apache POI"));
|
||||||
assertFalse("shorter string", StringUtil.endsWithIgnoreCase("Apache", "Apache POI"));
|
assertFalse("shorter string", StringUtil.endsWithIgnoreCase("Apache", "Apache POI"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void join() {
|
public void join() {
|
||||||
assertEquals("", StringUtil.join(",")); // degenerate case: nothing to join
|
assertEquals("", StringUtil.join(",")); // degenerate case: nothing to join
|
||||||
assertEquals("abc", StringUtil.join(",", "abc")); // degenerate case: one thing to join, no trailing comma
|
assertEquals("abc", StringUtil.join(",", "abc")); // degenerate case: one thing to join, no trailing comma
|
||||||
assertEquals("abc|def|ghi", StringUtil.join("|", "abc", "def", "ghi"));
|
assertEquals("abc|def|ghi", StringUtil.join("|", "abc", "def", "ghi"));
|
||||||
assertEquals("5|8.5|true|string", StringUtil.join("|", 5, 8.5, true, "string")); //assumes Locale prints number decimal point as a period rather than a comma
|
assertEquals("5|8.5|true|string", StringUtil.join("|", 5, 8.5, true, "string")); //assumes Locale prints number decimal point as a period rather than a comma
|
||||||
|
|
||||||
String[] arr = new String[] { "Apache", "POI", "project" };
|
String[] arr = new String[] { "Apache", "POI", "project" };
|
||||||
assertEquals("no separator", "ApachePOIproject", StringUtil.join(arr));
|
assertEquals("no separator", "ApachePOIproject", StringUtil.join(arr));
|
||||||
assertEquals("separator", "Apache POI project", StringUtil.join(arr, " "));
|
assertEquals("separator", "Apache POI project", StringUtil.join(arr, " "));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void count() {
|
public void count() {
|
||||||
String test = "Apache POI project\n\u00a9 Copyright 2016";
|
String test = "Apache POI project\n\u00a9 Copyright 2016";
|
||||||
// supports search in null or empty string
|
// supports search in null or empty string
|
||||||
assertEquals("null", 0, StringUtil.countMatches(null, 'A'));
|
assertEquals("null", 0, StringUtil.countMatches(null, 'A'));
|
||||||
assertEquals("empty string", 0, StringUtil.countMatches("", 'A'));
|
assertEquals("empty string", 0, StringUtil.countMatches("", 'A'));
|
||||||
|
|
||||||
assertEquals("normal", 2, StringUtil.countMatches(test, 'e'));
|
assertEquals("normal", 2, StringUtil.countMatches(test, 'e'));
|
||||||
assertEquals("normal, should not find a in escaped copyright", 1, StringUtil.countMatches(test, 'a'));
|
assertEquals("normal, should not find a in escaped copyright", 1, StringUtil.countMatches(test, 'a'));
|
||||||
|
|
||||||
// search for non-printable characters
|
// search for non-printable characters
|
||||||
assertEquals("null character", 0, StringUtil.countMatches(test, '\0'));
|
assertEquals("null character", 0, StringUtil.countMatches(test, '\0'));
|
||||||
assertEquals("CR", 0, StringUtil.countMatches(test, '\r'));
|
assertEquals("CR", 0, StringUtil.countMatches(test, '\r'));
|
||||||
assertEquals("LF", 1, StringUtil.countMatches(test, '\n'));
|
assertEquals("LF", 1, StringUtil.countMatches(test, '\n'));
|
||||||
|
|
||||||
// search for unicode characters
|
// search for unicode characters
|
||||||
assertEquals("Unicode", 1, StringUtil.countMatches(test, '\u00a9'));
|
assertEquals("Unicode", 1, StringUtil.countMatches(test, '\u00a9'));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue