Browse Source

BUG 64015 -- swap out java.util.BitSet for zaxxer's SparseBitSet

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1872445 13f79535-47bb-0310-9956-ffa450edef68
tags/REL_4_1_2
Tim Allison 4 years ago
parent
commit
e875bd8143

+ 2
- 0
build.gradle View File

compile 'com.sun.xml.bind:jaxb-impl:2.3.2' compile 'com.sun.xml.bind:jaxb-impl:2.3.2'
compile 'com.sun.xml.bind:jaxb-core:2.3.0.1' compile 'com.sun.xml.bind:jaxb-core:2.3.0.1'
compile 'javax.activation:activation:1.1.1' compile 'javax.activation:activation:1.1.1'
compile 'com.zaxxer:SparseBitSet:1.2'


testCompile 'junit:junit:4.12' testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:3.0.0' testCompile 'org.mockito:mockito-core:3.0.0'
compile 'org.apache.santuario:xmlsec:2.1.2' compile 'org.apache.santuario:xmlsec:2.1.2'
compile 'org.bouncycastle:bcpkix-jdk15on:1.62' compile 'org.bouncycastle:bcpkix-jdk15on:1.62'
compile 'com.github.virtuald:curvesapi:1.06' compile 'com.github.virtuald:curvesapi:1.06'
compile 'com.zaxxer:SparseBitSet:1.2'


// compile only, don't add it to our dist as it blows up the size // compile only, don't add it to our dist as it blows up the size
compile 'org.apache.xmlgraphics:batik-all:1.11' compile 'org.apache.xmlgraphics:batik-all:1.11'

+ 8
- 0
build.xml View File

<property name="main.activation.jar" location="${main.lib}/activation-1.1.1.jar"/> <property name="main.activation.jar" location="${main.lib}/activation-1.1.1.jar"/>
<property name="main.activation.url" <property name="main.activation.url"
value="${repository.m2}/maven2/javax/activation/activation/1.1.1/activation-1.1.1.jar"/> value="${repository.m2}/maven2/javax/activation/activation/1.1.1/activation-1.1.1.jar"/>
<property name="main.com.zaxxer.jar" location="${main.lib}/SparseBitSet-1.2.jar"/>
<property name="main.com.zaxxer.url"
value="${repository.m2}/maven2/com/zaxxer/SparseBitSet/1.2/SparseBitSet-1.2.jar"/>


<!-- xml signature libs --> <!-- xml signature libs -->
<property name="dsig.xmlsec.jar" location="${compile.lib}/xmlsec-2.1.2.jar"/> <property name="dsig.xmlsec.jar" location="${compile.lib}/xmlsec-2.1.2.jar"/>
<pathelement location="${main.xmlbind-impl.jar}"/> <pathelement location="${main.xmlbind-impl.jar}"/>
<pathelement location="${main.xmlbind-core.jar}"/> <pathelement location="${main.xmlbind-core.jar}"/>
<pathelement location="${main.activation.jar}"/> <pathelement location="${main.activation.jar}"/>
<pathelement location="${main.com.zaxxer.jar}"/>
</path> </path>


<!-- some libraries should only be required for compiling/running tests --> <!-- some libraries should only be required for compiling/running tests -->
<available file="${main.xmlbind-impl.jar}"/> <available file="${main.xmlbind-impl.jar}"/>
<available file="${main.xmlbind-core.jar}"/> <available file="${main.xmlbind-core.jar}"/>
<available file="${main.activation.jar}"/> <available file="${main.activation.jar}"/>
<available file="${main.com.zaxxer.jar}"/>


<!-- we had some CI failures when the extracted files for JaCoCo were missing somehow... --> <!-- we had some CI failures when the extracted files for JaCoCo were missing somehow... -->
<available file="${main.lib}/jacocoagent.jar"/> <available file="${main.lib}/jacocoagent.jar"/>
<downloadfile src="${main.xmlbind-impl.url}" dest="${main.xmlbind-impl.jar}"/> <downloadfile src="${main.xmlbind-impl.url}" dest="${main.xmlbind-impl.jar}"/>
<downloadfile src="${main.xmlbind-core.url}" dest="${main.xmlbind-core.jar}"/> <downloadfile src="${main.xmlbind-core.url}" dest="${main.xmlbind-core.jar}"/>
<downloadfile src="${main.activation.url}" dest="${main.activation.jar}"/> <downloadfile src="${main.activation.url}" dest="${main.activation.jar}"/>
<downloadfile src="${main.com.zaxxer.url}" dest="${main.com.zaxxer.jar}"/>
<unzip src="${jacoco.zip}" dest="."> <unzip src="${jacoco.zip}" dest=".">
<patternset> <patternset>
<include name="lib/*.jar"/> <include name="lib/*.jar"/>
<include name="activation-*.jar"/> <include name="activation-*.jar"/>
<include name="junit-*.jar"/> <include name="junit-*.jar"/>
<include name="log4j-*.jar"/> <include name="log4j-*.jar"/>
<include name="SparseBitSet-*.jar"/>
</fileset> </fileset>
<globmapper from="*" to="${zipdir}/lib/*"/> <globmapper from="*" to="${zipdir}/lib/*"/>
</mappedresources> </mappedresources>
<auxClasspath path="${main.xmlbind-impl.jar}" /> <auxClasspath path="${main.xmlbind-impl.jar}" />
<auxClasspath path="${main.xmlbind-core.jar}" /> <auxClasspath path="${main.xmlbind-core.jar}" />
<auxClasspath path="${main.activation.jar}" /> <auxClasspath path="${main.activation.jar}" />
<auxClasspath path="${main.com.zaxxer.jar}" />
<auxClasspath path="${svg.batik-all.jar}"/> <auxClasspath path="${svg.batik-all.jar}"/>
<auxClasspath path="${svg.xml-apis-ext.jar}"/> <auxClasspath path="${svg.xml-apis-ext.jar}"/>
<auxClasspath path="${svg.xmlgraphics-commons.jar}"/> <auxClasspath path="${svg.xmlgraphics-commons.jar}"/>

+ 5
- 0
maven/poi.pom View File

<artifactId>commons-math3</artifactId> <artifactId>commons-math3</artifactId>
<version>3.6.1</version> <version>3.6.1</version>
</dependency> </dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>SparseBitSet</artifactId>
<version>1.2</version>
</dependency>


<dependency> <dependency>
<groupId>org.hamcrest</groupId> <groupId>org.hamcrest</groupId>

+ 5
- 0
sonar/main/pom.xml View File

<artifactId>commons-codec</artifactId> <artifactId>commons-codec</artifactId>
<version>1.13</version> <version>1.13</version>
</dependency> </dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>SparseBitSet</artifactId>
<version>1.2</version>
</dependency>
<dependency> <dependency>
<groupId>commons-logging</groupId> <groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId> <artifactId>commons-logging</artifactId>

+ 2
- 2
src/java/org/apache/poi/ddf/EscherDggRecord.java View File



import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.BitSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.function.Supplier; import java.util.function.Supplier;


import com.zaxxer.sparsebits.SparseBitSet;
import org.apache.poi.common.usermodel.GenericRecord; import org.apache.poi.common.usermodel.GenericRecord;
import org.apache.poi.util.GenericRecordUtil; import org.apache.poi.util.GenericRecordUtil;
import org.apache.poi.util.LittleEndian; import org.apache.poi.util.LittleEndian;
* @return the next available drawing group id * @return the next available drawing group id
*/ */
public short findNewDrawingGroupId() { public short findNewDrawingGroupId() {
BitSet bs = new BitSet();
SparseBitSet bs = new SparseBitSet();
bs.set(0); bs.set(0);
for (FileIdCluster fic : field_5_fileIdClusters) { for (FileIdCluster fic : field_5_fileIdClusters) {
bs.set(fic.getDrawingGroupId()); bs.set(fic.getDrawingGroupId());

+ 5
- 5
src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java View File

import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.util.BitSet;


import javax.crypto.BadPaddingException; import javax.crypto.BadPaddingException;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException; import javax.crypto.IllegalBlockSizeException;
import javax.crypto.ShortBufferException; import javax.crypto.ShortBufferException;


import com.zaxxer.sparsebits.SparseBitSet;
import org.apache.poi.EncryptedDocumentException; import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.POIFSWriterEvent; import org.apache.poi.poifs.filesystem.POIFSWriterEvent;
private final int chunkBits; private final int chunkBits;


private final byte[] chunk; private final byte[] chunk;
private final BitSet plainByteFlags;
private final SparseBitSet plainByteFlags;
private final File fileOut; private final File fileOut;
private final DirectoryNode dir; private final DirectoryNode dir;


this.chunkSize = chunkSize; this.chunkSize = chunkSize;
int cs = chunkSize == STREAMING ? 4096 : chunkSize; int cs = chunkSize == STREAMING ? 4096 : chunkSize;
this.chunk = IOUtils.safelyAllocate(cs, MAX_RECORD_LENGTH); this.chunk = IOUtils.safelyAllocate(cs, MAX_RECORD_LENGTH);
this.plainByteFlags = new BitSet(cs);
this.plainByteFlags = new SparseBitSet(cs);
this.chunkBits = Integer.bitCount(cs-1); this.chunkBits = Integer.bitCount(cs-1);
this.fileOut = TempFile.createTempFile("encrypted_package", "crypt"); this.fileOut = TempFile.createTempFile("encrypted_package", "crypt");
this.fileOut.deleteOnExit(); this.fileOut.deleteOnExit();
this.chunkSize = chunkSize; this.chunkSize = chunkSize;
int cs = chunkSize == STREAMING ? 4096 : chunkSize; int cs = chunkSize == STREAMING ? 4096 : chunkSize;
this.chunk = IOUtils.safelyAllocate(cs, MAX_RECORD_LENGTH); this.chunk = IOUtils.safelyAllocate(cs, MAX_RECORD_LENGTH);
this.plainByteFlags = new BitSet(cs);
this.plainByteFlags = new SparseBitSet(cs);
this.chunkBits = Integer.bitCount(cs-1); this.chunkBits = Integer.bitCount(cs-1);
this.fileOut = null; this.fileOut = null;
this.dir = null; this.dir = null;
return chunk; return chunk;
} }


protected BitSet getPlainByteFlags() {
protected SparseBitSet getPlainByteFlags() {
return plainByteFlags; return plainByteFlags;
} }



+ 2
- 2
src/java/org/apache/poi/poifs/crypt/xor/XOREncryptor.java View File

import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.util.BitSet;


import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;


import com.zaxxer.sparsebits.SparseBitSet;
import org.apache.poi.EncryptedDocumentException; import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.poifs.crypt.ChunkedCipherOutputStream; import org.apache.poi.poifs.crypt.ChunkedCipherOutputStream;
import org.apache.poi.poifs.crypt.CryptoFunctions; import org.apache.poi.poifs.crypt.CryptoFunctions;


final int start = Math.max(posInChunk-(recordEnd-recordStart), 0); final int start = Math.max(posInChunk-(recordEnd-recordStart), 0);


final BitSet plainBytes = getPlainByteFlags();
final SparseBitSet plainBytes = getPlainByteFlags();
final byte[] xorArray = getEncryptionInfo().getEncryptor().getSecretKey().getEncoded(); final byte[] xorArray = getEncryptionInfo().getEncryptor().getSecretKey().getEncoded();
final byte[] chunk = getChunk(); final byte[] chunk = getChunk();
final byte[] plain = (plainBytes.isEmpty()) ? null : chunk.clone(); final byte[] plain = (plainBytes.isEmpty()) ? null : chunk.clone();

+ 27
- 0
src/java/org/apache/poi/sl/extractor/SlideShowExtractor.java View File

import java.util.function.Function; import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;


import com.zaxxer.sparsebits.SparseBitSet;
import org.apache.poi.extractor.POITextExtractor; import org.apache.poi.extractor.POITextExtractor;
import org.apache.poi.sl.usermodel.MasterSheet; import org.apache.poi.sl.usermodel.MasterSheet;
import org.apache.poi.sl.usermodel.Notes; import org.apache.poi.sl.usermodel.Notes;
* @param bold use {@code true} for bold TextRuns, {@code false} for non-bold ones and * @param bold use {@code true} for bold TextRuns, {@code false} for non-bold ones and
* {@code null} if it doesn't matter * {@code null} if it doesn't matter
* @return a bitset with the marked/used codepoints * @return a bitset with the marked/used codepoints
* @deprecated use {@link #getCodepointsInSparseBitSet(String, Boolean, Boolean)}
*/ */
@Deprecated
public BitSet getCodepoints(String typeface, Boolean italic, Boolean bold) { public BitSet getCodepoints(String typeface, Boolean italic, Boolean bold) {
final BitSet glyphs = new BitSet(); final BitSet glyphs = new BitSet();


return glyphs; return glyphs;
} }


/**
* Extract the used codepoints for font embedding / subsetting
* @param typeface the typeface/font family of the textruns to examine
* @param italic use {@code true} for italic TextRuns, {@code false} for non-italic ones and
* {@code null} if it doesn't matter
* @param bold use {@code true} for bold TextRuns, {@code false} for non-bold ones and
* {@code null} if it doesn't matter
* @return a bitset with the marked/used codepoints
*/
public SparseBitSet getCodepointsInSparseBitSet(String typeface, Boolean italic, Boolean bold) {
final SparseBitSet glyphs = new SparseBitSet();

Predicate<Object> filterOld = filter;
try {
filter = o -> filterFonts(o, typeface, italic, bold);
slideshow.getSlides().forEach(slide ->
getText(slide, s -> s.codePoints().forEach(glyphs::set))
);
} finally {
filter = filterOld;
}

return glyphs;
}
private static boolean filterFonts(Object o, String typeface, Boolean italic, Boolean bold) { private static boolean filterFonts(Object o, String typeface, Boolean italic, Boolean bold) {
if (!(o instanceof TextRun)) { if (!(o instanceof TextRun)) {
return false; return false;

+ 2
- 2
src/java/org/apache/poi/ss/format/CellNumberFormatter.java View File

import java.text.DecimalFormatSymbols; import java.text.DecimalFormatSymbols;
import java.text.FieldPosition; import java.text.FieldPosition;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections; import java.util.Collections;
import java.util.Formatter; import java.util.Formatter;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;


import com.zaxxer.sparsebits.SparseBitSet;
import org.apache.poi.util.LocaleUtil; import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger; import org.apache.poi.util.POILogger;
Iterator<CellNumberStringMod> changes = mods.iterator(); Iterator<CellNumberStringMod> changes = mods.iterator();
CellNumberStringMod nextChange = (changes.hasNext() ? changes.next() : null); CellNumberStringMod nextChange = (changes.hasNext() ? changes.next() : null);
// records chars already deleted // records chars already deleted
BitSet deletedChars = new BitSet();
SparseBitSet deletedChars = new SparseBitSet();
int adjust = 0; int adjust = 0;
for (Special s : specials) { for (Special s : specials) {
int adjustedPos = s.pos + adjust; int adjustedPos = s.pos + adjust;

+ 9
- 2
src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePartCollection.java View File

package org.apache.poi.openxml4j.opc; package org.apache.poi.openxml4j.opc;


import java.io.Serializable; import java.io.Serializable;
import java.util.BitSet;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;


import com.zaxxer.sparsebits.SparseBitSet;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.InvalidOperationException; import org.apache.poi.openxml4j.exceptions.InvalidOperationException;


return packagePartLookup.keySet().stream() return packagePartLookup.keySet().stream()
.mapToInt(indexFromName) .mapToInt(indexFromName)
.collect(BitSet::new, BitSet::set, BitSet::or).nextClearBit(1);
.collect(MySparseBitSet::new, MySparseBitSet::set, MySparseBitSet::myOr).nextClearBit(1);
} }
private class MySparseBitSet extends SparseBitSet {

public void myOr(MySparseBitSet other) {
this.or(other);
}
}
} }

+ 2
- 2
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java View File

import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.BitSet;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;


import javax.xml.namespace.QName; import javax.xml.namespace.QName;


import com.zaxxer.sparsebits.SparseBitSet;
import org.apache.poi.ooxml.POIXMLDocumentPart; import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ooxml.POIXMLException; import org.apache.poi.ooxml.POIXMLException;
import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.OPCPackage;
private Map<Integer, XSLFSimpleShape> _placeholderByIdMap; private Map<Integer, XSLFSimpleShape> _placeholderByIdMap;
private Map<Integer, XSLFSimpleShape> _placeholderByTypeMap; private Map<Integer, XSLFSimpleShape> _placeholderByTypeMap;


private final BitSet shapeIds = new BitSet();
private final SparseBitSet shapeIds = new SparseBitSet();


protected XSLFSheet() { protected XSLFSheet() {
super(); super();

+ 2
- 2
src/ooxml/java/org/apache/poi/xssf/binary/XSSFBHyperlinksTable.java View File

import java.io.InputStream; import java.io.InputStream;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.BitSet;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;


import com.zaxxer.sparsebits.SparseBitSet;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.PackageRelationship;
@Internal @Internal
public class XSSFBHyperlinksTable { public class XSSFBHyperlinksTable {


private static final BitSet RECORDS = new BitSet();
private static final SparseBitSet RECORDS = new SparseBitSet();




static { static {

+ 3
- 3
src/ooxml/java/org/apache/poi/xssf/binary/XSSFBParser.java View File



import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.BitSet;


import com.zaxxer.sparsebits.SparseBitSet;
import org.apache.poi.util.IOUtils; import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal; import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndianInputStream; import org.apache.poi.util.LittleEndianInputStream;
private static final int MAX_RECORD_LENGTH = 1_000_000; private static final int MAX_RECORD_LENGTH = 1_000_000;


private final LittleEndianInputStream is; private final LittleEndianInputStream is;
private final BitSet records;
private final SparseBitSet records;


public XSSFBParser(InputStream is) { public XSSFBParser(InputStream is) {
this.is = new LittleEndianInputStream(is); this.is = new LittleEndianInputStream(is);
* @param is inputStream * @param is inputStream
* @param bitSet call {@link #handleRecord(int, byte[])} only on those records in this bitSet * @param bitSet call {@link #handleRecord(int, byte[])} only on those records in this bitSet
*/ */
protected XSSFBParser(InputStream is, BitSet bitSet) {
protected XSSFBParser(InputStream is, SparseBitSet bitSet) {
this.is = new LittleEndianInputStream(is); this.is = new LittleEndianInputStream(is);
records = bitSet; records = bitSet;
} }

+ 2
- 2
src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFBReader.java View File

import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections; import java.util.Collections;
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.Set; import java.util.Set;


import com.zaxxer.sparsebits.SparseBitSet;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.exceptions.OpenXML4JException; import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.OPCPackage;




private static class PathExtractor extends XSSFBParser { private static class PathExtractor extends XSSFBParser {
private static BitSet RECORDS = new BitSet();
private static SparseBitSet RECORDS = new SparseBitSet();
static { static {
RECORDS.set(XSSFBRecordType.BrtAbsPath15.getId()); RECORDS.set(XSSFBRecordType.BrtAbsPath15.getId());
} }

Loading…
Cancel
Save