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