tag r1847494 as 4.0.1

git-svn-id: https://svn.apache.org/repos/asf/poi/tags/REL_4_0_1@1847495 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Andreas Beeker 2018-11-26 21:27:30 +00:00
commit 3ad99da86e
50 changed files with 507 additions and 246 deletions

View File

@ -1950,6 +1950,7 @@ under the License.
<mapper> <mapper>
<chainedmapper> <chainedmapper>
<filtermapper> <filtermapper>
<replaceregex pattern=".jar" replace="" flags="g"/>
<replaceregex pattern="ooxml-lite" replace="ooxml-schemas" flags="g"/> <replaceregex pattern="ooxml-lite" replace="ooxml-schemas" flags="g"/>
<replaceregex pattern="(.java|.src)$$" replace="-sources"/> <replaceregex pattern="(.java|.src)$$" replace="-sources"/>
<replaceregex pattern=".*(?:build|src).?(.*)?" replace="\1"/> <replaceregex pattern=".*(?:build|src).?(.*)?" replace="\1"/>
@ -2112,6 +2113,7 @@ under the License.
sonar/*/src/**, sonar/*/src/**,
compile-lib/**, compile-lib/**,
ooxml-lib/**, ooxml-lib/**,
ooxml-testlib/**,
scripts/**, scripts/**,
TEST*, TEST*,
*.ipr, *.ipr,
@ -2452,7 +2454,7 @@ under the License.
<copy todir="${repo}"> <copy todir="${repo}">
<mappedresources> <mappedresources>
<!-- add sha-512 when nexus rules are updated (1/2) --> <!-- add sha-512 when nexus rules are updated (1/2) -->
<fileset dir="build/dist/maven" includes="@{artifactId}/**" excludes="**/*.sha512"/> <fileset dir="build/dist/maven" includes="@{artifactId}/**" excludes="**/*.sha512,**/*.sha256"/>
<regexpmapper from="^([^/]+)/(.*)$$" to="org/apache/poi/\1/${version.id}/\2" handledirsep="true"/> <regexpmapper from="^([^/]+)/(.*)$$" to="org/apache/poi/\1/${version.id}/\2" handledirsep="true"/>
</mappedresources> </mappedresources>
</copy> </copy>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.apache.poi</groupId> <groupId>org.apache.poi</groupId>
<artifactId>poi-parent</artifactId> <artifactId>poi-parent</artifactId>
<version>4.0.1-SNAPSHOT</version> <version>4.0.2-SNAPSHOT</version>
</parent> </parent>
<artifactId>poi-examples</artifactId> <artifactId>poi-examples</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.apache.poi</groupId> <groupId>org.apache.poi</groupId>
<artifactId>poi-parent</artifactId> <artifactId>poi-parent</artifactId>
<version>4.0.1-SNAPSHOT</version> <version>4.0.2-SNAPSHOT</version>
</parent> </parent>
<artifactId>poi-excelant</artifactId> <artifactId>poi-excelant</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.apache.poi</groupId> <groupId>org.apache.poi</groupId>
<artifactId>poi-parent</artifactId> <artifactId>poi-parent</artifactId>
<version>4.0.1-SNAPSHOT</version> <version>4.0.2-SNAPSHOT</version>
</parent> </parent>
<artifactId>poi-main</artifactId> <artifactId>poi-main</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.apache.poi</groupId> <groupId>org.apache.poi</groupId>
<artifactId>poi-parent</artifactId> <artifactId>poi-parent</artifactId>
<version>4.0.1-SNAPSHOT</version> <version>4.0.2-SNAPSHOT</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
<artifactId>poi-ooxml-schema-encryption</artifactId> <artifactId>poi-ooxml-schema-encryption</artifactId>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.apache.poi</groupId> <groupId>org.apache.poi</groupId>
<artifactId>poi-parent</artifactId> <artifactId>poi-parent</artifactId>
<version>4.0.1-SNAPSHOT</version> <version>4.0.2-SNAPSHOT</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
<artifactId>poi-ooxml-schema-security</artifactId> <artifactId>poi-ooxml-schema-security</artifactId>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.apache.poi</groupId> <groupId>org.apache.poi</groupId>
<artifactId>poi-parent</artifactId> <artifactId>poi-parent</artifactId>
<version>4.0.1-SNAPSHOT</version> <version>4.0.2-SNAPSHOT</version>
<relativePath>..</relativePath> <relativePath>..</relativePath>
</parent> </parent>
<artifactId>poi-ooxml-schema</artifactId> <artifactId>poi-ooxml-schema</artifactId>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.apache.poi</groupId> <groupId>org.apache.poi</groupId>
<artifactId>poi-parent</artifactId> <artifactId>poi-parent</artifactId>
<version>4.0.1-SNAPSHOT</version> <version>4.0.2-SNAPSHOT</version>
</parent> </parent>
<artifactId>poi-ooxml</artifactId> <artifactId>poi-ooxml</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>

View File

@ -4,7 +4,7 @@
<groupId>org.apache.poi</groupId> <groupId>org.apache.poi</groupId>
<artifactId>poi-parent</artifactId> <artifactId>poi-parent</artifactId>
<packaging>pom</packaging> <packaging>pom</packaging>
<version>4.0.1-SNAPSHOT</version> <version>4.0.2-SNAPSHOT</version>
<name>Apache POI - the Java API for Microsoft Documents</name> <name>Apache POI - the Java API for Microsoft Documents</name>
<description>Maven build of Apache POI for Sonar checks</description> <description>Maven build of Apache POI for Sonar checks</description>
<url>http://poi.apache.org/</url> <url>http://poi.apache.org/</url>

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>org.apache.poi</groupId> <groupId>org.apache.poi</groupId>
<artifactId>poi-parent</artifactId> <artifactId>poi-parent</artifactId>
<version>4.0.1-SNAPSHOT</version> <version>4.0.2-SNAPSHOT</version>
</parent> </parent>
<artifactId>poi-scratchpad</artifactId> <artifactId>poi-scratchpad</artifactId>
<packaging>jar</packaging> <packaging>jar</packaging>

View File

@ -289,6 +289,7 @@ public class TestAllFiles {
"document/Bug50955.doc", "document/Bug50955.doc",
"document/57843.doc", "document/57843.doc",
"slideshow/PPT95.ppt", "slideshow/PPT95.ppt",
"slideshow/pp40only.ppt",
"slideshow/Divino_Revelado.pptx", "slideshow/Divino_Revelado.pptx",
"openxml4j/OPCCompliance_CoreProperties_DCTermsNamespaceLimitedUseFAIL.docx", "openxml4j/OPCCompliance_CoreProperties_DCTermsNamespaceLimitedUseFAIL.docx",
"openxml4j/OPCCompliance_CoreProperties_DoNotUseCompatibilityMarkupFAIL.docx", "openxml4j/OPCCompliance_CoreProperties_DoNotUseCompatibilityMarkupFAIL.docx",

View File

@ -35,7 +35,6 @@ import java.util.Iterator;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerException;
import org.apache.poi.EncryptedDocumentException; import org.apache.poi.EncryptedDocumentException;
@ -148,7 +147,7 @@ public class XSSFFileHandler extends SpreadsheetHandler {
} }
private void exportToXML(XSSFWorkbook wb) throws SAXException, private void exportToXML(XSSFWorkbook wb) throws SAXException,
ParserConfigurationException, TransformerException { TransformerException {
for (XSSFMap map : wb.getCustomXMLMappings()) { for (XSSFMap map : wb.getCustomXMLMappings()) {
XSSFExportToXml exporter = new XSSFExportToXml(map); XSSFExportToXml exporter = new XSSFExportToXml(map);
@ -165,7 +164,6 @@ public class XSSFFileHandler extends SpreadsheetHandler {
// zip-bomb // zip-bomb
EXPECTED_ADDITIONAL_FAILURES.add("spreadsheet/54764.xlsx"); EXPECTED_ADDITIONAL_FAILURES.add("spreadsheet/54764.xlsx");
EXPECTED_ADDITIONAL_FAILURES.add("spreadsheet/54764-2.xlsx"); EXPECTED_ADDITIONAL_FAILURES.add("spreadsheet/54764-2.xlsx");
EXPECTED_ADDITIONAL_FAILURES.add("spreadsheet/54764.xlsx");
EXPECTED_ADDITIONAL_FAILURES.add("spreadsheet/poc-xmlbomb.xlsx"); EXPECTED_ADDITIONAL_FAILURES.add("spreadsheet/poc-xmlbomb.xlsx");
EXPECTED_ADDITIONAL_FAILURES.add("spreadsheet/poc-xmlbomb-empty.xlsx"); EXPECTED_ADDITIONAL_FAILURES.add("spreadsheet/poc-xmlbomb-empty.xlsx");
// strict OOXML // strict OOXML
@ -185,18 +183,19 @@ public class XSSFFileHandler extends SpreadsheetHandler {
public void handleAdditional(File file) throws Exception { public void handleAdditional(File file) throws Exception {
// redirect stdout as the examples often write lots of text // redirect stdout as the examples often write lots of text
PrintStream oldOut = System.out; PrintStream oldOut = System.out;
String testFile = file.getParentFile().getName() + "/" + file.getName();
try { try {
System.setOut(new NullPrintStream()); System.setOut(new NullPrintStream());
FromHowTo.main(new String[]{file.getAbsolutePath()}); FromHowTo.main(new String[]{file.getAbsolutePath()});
XLSX2CSV.main(new String[]{file.getAbsolutePath()}); XLSX2CSV.main(new String[]{file.getAbsolutePath()});
assertFalse("Expected Extraction to fail for file " + file + " and handler " + this + ", but did not fail!", assertFalse("Expected Extraction to fail for file " + file + " and handler " + this + ", but did not fail!",
EXPECTED_ADDITIONAL_FAILURES.contains(file.getParentFile().getName() + "/" + file.getName())); EXPECTED_ADDITIONAL_FAILURES.contains(testFile));
} catch (OLE2NotOfficeXmlFileException e) { } catch (OLE2NotOfficeXmlFileException e) {
// we have some files that are not actually OOXML and thus cannot be tested here // we have some files that are not actually OOXML and thus cannot be tested here
} catch (IllegalArgumentException | InvalidFormatException | POIXMLException | IOException e) { } catch (IllegalArgumentException | InvalidFormatException | POIXMLException | IOException e) {
if(!EXPECTED_ADDITIONAL_FAILURES.contains(file.getParentFile().getName() + "/" + file.getName())) { if(!EXPECTED_ADDITIONAL_FAILURES.contains(testFile)) {
throw e; throw e;
} }
} finally { } finally {

View File

@ -36,7 +36,7 @@ import org.apache.poi.util.POILogger;
* Supports reading and writing of variant data.<p> * Supports reading and writing of variant data.<p>
* *
* <strong>FIXME (3):</strong> Reading and writing should be made more * <strong>FIXME (3):</strong> Reading and writing should be made more
* uniform than it is now. The following items should be resolved:<p> * uniform than it is now. The following items should be resolved:
* *
* <ul> * <ul>
* *

View File

@ -33,8 +33,11 @@ import org.apache.poi.hpsf.SummaryInformation;
* The methods {@link #getSummaryInformationProperties} and {@link * The methods {@link #getSummaryInformationProperties} and {@link
* #getDocumentSummaryInformationProperties} return singleton {@link * #getDocumentSummaryInformationProperties} return singleton {@link
* PropertyIDMap}s. An application that wants to extend these maps * PropertyIDMap}s. An application that wants to extend these maps
* should treat them as unmodifiable, copy them and modifiy the * should treat them as unmodifiable, copy them and modify the
* copies. * copies.
*
* Trying to modify the map directly will cause exceptions
* {@link UnsupportedOperationException} to be thrown.
*/ */
public class PropertyIDMap implements Map<Long,String> { public class PropertyIDMap implements Map<Long,String> {
@ -490,11 +493,13 @@ public class PropertyIDMap implements Map<Long,String> {
@Override @Override
public String put(Long key, String value) { public String put(Long key, String value) {
//noinspection ConstantConditions
return idMap.put(key, value); return idMap.put(key, value);
} }
@Override @Override
public String remove(Object key) { public String remove(Object key) {
//noinspection ConstantConditions
return idMap.remove(key); return idMap.remove(key);
} }

View File

@ -2276,6 +2276,8 @@ public final class InternalWorkbook {
/** /**
* Only for internal calls - code based on this is not supported ... * Only for internal calls - code based on this is not supported ...
*
* @return The list of records.
*/ */
@Internal @Internal
public WorkbookRecordList getWorkbookRecordList() { public WorkbookRecordList getWorkbookRecordList() {

View File

@ -33,8 +33,9 @@ import org.apache.poi.util.LittleEndianInputStream;
import org.apache.poi.util.RecordFormatException; import org.apache.poi.util.RecordFormatException;
/** /**
* Title: Record Input Stream<P> * Title: Record Input Stream
* Description: Wraps a stream and provides helper methods for the construction of records.<P> *
* Description: Wraps a stream and provides helper methods for the construction of records.
*/ */
public final class RecordInputStream implements LittleEndianInput { public final class RecordInputStream implements LittleEndianInput {
@ -194,11 +195,11 @@ public final class RecordInputStream implements LittleEndianInput {
private int readNextSid() { private int readNextSid() {
int nAvailable = _bhi.available(); int nAvailable = _bhi.available();
if (nAvailable < EOFRecord.ENCODED_SIZE) { if (nAvailable < EOFRecord.ENCODED_SIZE) {
if (nAvailable > 0) { /*if (nAvailable > 0) {
// some scrap left over? // some scrap left over?
// ex45582-22397.xls has one extra byte after the last record // ex45582-22397.xls has one extra byte after the last record
// Excel reads that file OK // Excel reads that file OK
} }*/
return INVALID_SID_VALUE; return INVALID_SID_VALUE;
} }
int result = _bhi.readRecordSID(); int result = _bhi.readRecordSID();
@ -305,14 +306,13 @@ public final class RecordInputStream implements LittleEndianInput {
@Override @Override
public double readDouble() { public double readDouble() {
long valueLongBits = readLong(); long valueLongBits = readLong();
double result = Double.longBitsToDouble(valueLongBits); /*if (Double.isNaN(result)) {
if (Double.isNaN(result)) {
// YK: Excel doesn't write NaN but instead converts the cell type into {@link CellType#ERROR}. // YK: Excel doesn't write NaN but instead converts the cell type into {@link CellType#ERROR}.
// HSSF prior to version 3.7 had a bug: it could write Double.NaN but could not read such a file back. // HSSF prior to version 3.7 had a bug: it could write Double.NaN but could not read such a file back.
// This behavior was fixed in POI-3.7. // This behavior was fixed in POI-3.7.
//throw new RuntimeException("Did not expect to read NaN"); // (Because Excel typically doesn't write NaN) //throw new RuntimeException("Did not expect to read NaN"); // (Because Excel typically doesn't write NaN)
} }*/
return result; return Double.longBitsToDouble(valueLongBits);
} }
public void readPlain(byte[] buf, int off, int len) { public void readPlain(byte[] buf, int off, int len) {

View File

@ -161,7 +161,7 @@ public final class SSTRecord extends ContinuableRecord {
* <P> * <P>
* The data consists of sets of string data. This string data is * The data consists of sets of string data. This string data is
* arranged as follows: * arranged as follows:
* <P> * </P><P>
* <pre> * <pre>
* short string_length; // length of string data * short string_length; // length of string data
* byte string_flag; // flag specifying special string * byte string_flag; // flag specifying special string
@ -176,9 +176,9 @@ public final class SSTRecord extends ContinuableRecord {
* byte[] extension; // optional extension (length of array * byte[] extension; // optional extension (length of array
* // is extend_length) * // is extend_length)
* </pre> * </pre>
* <P> * </P><P>
* The string_flag is bit mapped as follows: * The string_flag is bit mapped as follows:
* <P> * </P><P>
* <TABLE summary="string_flag mapping"> * <TABLE summary="string_flag mapping">
* <TR> * <TR>
* <TH>Bit number</TH> * <TH>Bit number</TH>
@ -232,7 +232,7 @@ public final class SSTRecord extends ContinuableRecord {
* associated data. The UnicodeString class can handle the byte[] * associated data. The UnicodeString class can handle the byte[]
* vs short[] nature of the actual string data * vs short[] nature of the actual string data
* *
* @param in the RecordInputstream to read the record from * @param in the RecordInputStream to read the record from
*/ */
public SSTRecord(RecordInputStream in) { public SSTRecord(RecordInputStream in) {
// this method is ALWAYS called after construction -- using // this method is ALWAYS called after construction -- using

View File

@ -77,7 +77,7 @@ public final class SharedFormulaRecord extends SharedValueRecordBase {
public String toString() public String toString()
{ {
StringBuffer buffer = new StringBuffer(); StringBuilder buffer = new StringBuilder();
buffer.append("[SHARED FORMULA (").append(HexDump.intToHex(sid)).append("]\n"); buffer.append("[SHARED FORMULA (").append(HexDump.intToHex(sid)).append("]\n");
buffer.append(" .range = ").append(getRange()).append("\n"); buffer.append(" .range = ").append(getRange()).append("\n");
@ -99,6 +99,10 @@ public final class SharedFormulaRecord extends SharedValueRecordBase {
} }
/** /**
* Convert formula into an array of {@link Ptg} tokens.
*
* @param formula The record to break into tokens, cannot be null
*
* @return the equivalent {@link Ptg} array that the formula would have, were it not shared. * @return the equivalent {@link Ptg} array that the formula would have, were it not shared.
*/ */
public Ptg[] getFormulaTokens(FormulaRecord formula) { public Ptg[] getFormulaTokens(FormulaRecord formula) {

View File

@ -42,6 +42,8 @@ public abstract class SharedValueRecordBase extends StandardRecord {
/** /**
* reads only the range (1 {@link CellRangeAddress8Bit}) from the stream * reads only the range (1 {@link CellRangeAddress8Bit}) from the stream
*
* @param in The interface for reading the record data.
*/ */
public SharedValueRecordBase(LittleEndianInput in) { public SharedValueRecordBase(LittleEndianInput in) {
_range = new CellRangeAddress8Bit(in); _range = new CellRangeAddress8Bit(in);
@ -99,14 +101,12 @@ public abstract class SharedValueRecordBase extends StandardRecord {
&& r.getLastColumn() >= colIx; && r.getLastColumn() >= colIx;
} }
/** /**
* @return {@code true} if (rowIx, colIx) describes the first cell in this shared value
* object's range
*
* @param rowIx the row index * @param rowIx the row index
* @param colIx the column index * @param colIx the column index
* *
* @return {@code true} if its the first cell in this shared value object range * @return {@code true} if (rowIx, colIx) describes the first cell in this shared value
* * object's range
*
* @see #getRange() * @see #getRange()
*/ */
public final boolean isFirstCell(int rowIx, int colIx) { public final boolean isFirstCell(int rowIx, int colIx) {

View File

@ -78,7 +78,7 @@ public enum FileMagic {
/** PDF document */ /** PDF document */
PDF("%PDF"), PDF("%PDF"),
/** Some different HTML documents */ /** Some different HTML documents */
HTML("<!DOCTYP".getBytes(UTF_8), "<html".getBytes(UTF_8)), HTML("<!DOCTYP".getBytes(UTF_8), "<html".getBytes(UTF_8), "<HTML".getBytes(UTF_8)),
WORD2(new byte[]{ (byte)0xdb, (byte)0xa5, 0x2d, 0x00}), WORD2(new byte[]{ (byte)0xdb, (byte)0xa5, 0x2d, 0x00}),
// keep UNKNOWN always as last enum! // keep UNKNOWN always as last enum!
/** UNKNOWN magic */ /** UNKNOWN magic */
@ -101,17 +101,8 @@ public enum FileMagic {
public static FileMagic valueOf(byte[] magic) { public static FileMagic valueOf(byte[] magic) {
for (FileMagic fm : values()) { for (FileMagic fm : values()) {
int i=0;
boolean found = true;
for (byte[] ma : fm.magic) { for (byte[] ma : fm.magic) {
for (byte m : ma) { if (findMagic(ma, magic)) {
byte d = magic[i++];
if (!(d == m || (m == 0x70 && (d == 0x10 || d == 0x20 || d == 0x40)))) {
found = false;
break;
}
}
if (found) {
return fm; return fm;
} }
} }
@ -119,6 +110,17 @@ public enum FileMagic {
return UNKNOWN; return UNKNOWN;
} }
private static boolean findMagic(byte[] cmp, byte[] actual) {
int i=0;
for (byte m : cmp) {
byte d = actual[i++];
if (!(d == m || (m == 0x70 && (d == 0x10 || d == 0x20 || d == 0x40)))) {
return false;
}
}
return true;
}
/** /**
* Get the file magic of the supplied {@link File}<p> * Get the file magic of the supplied {@link File}<p>

View File

@ -29,7 +29,10 @@ import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.TreeMap;
import java.util.function.BiFunction;
import org.apache.poi.sl.usermodel.AbstractColorStyle; import org.apache.poi.sl.usermodel.AbstractColorStyle;
import org.apache.poi.sl.usermodel.ColorStyle; import org.apache.poi.sl.usermodel.ColorStyle;
@ -197,28 +200,17 @@ public class DrawPaint {
@Override @Override
public int getShade() { public int getShade() {
int shade = orig.getShade(); return scale(orig.getShade(), PaintModifier.DARKEN_LESS, PaintModifier.DARKEN);
switch (modifier) {
case DARKEN:
return Math.min(100000, Math.max(0,shade)+40000);
case DARKEN_LESS:
return Math.min(100000, Math.max(0,shade)+20000);
default:
return shade;
}
} }
@Override @Override
public int getTint() { public int getTint() {
int tint = orig.getTint(); return scale(orig.getTint(), PaintModifier.LIGHTEN_LESS, PaintModifier.LIGHTEN);
switch (modifier) { }
case LIGHTEN:
return Math.min(100000, Math.max(0,tint)+40000); private int scale(int value, PaintModifier lessModifier, PaintModifier moreModifier) {
case LIGHTEN_LESS: int delta = (modifier == lessModifier ? 20000 : (modifier == moreModifier ? 40000 : 0));
return Math.min(100000, Math.max(0,tint)+20000); return Math.min(100000, Math.max(0,value)+delta);
default:
return tint;
}
} }
}; };
@ -300,7 +292,7 @@ public class DrawPaint {
Color result = color.getColor(); Color result = color.getColor();
double alpha = getAlpha(result, color); double alpha = getAlpha(result, color);
double hsl[] = RGB2HSL(result); // values are in the range [0..100] (usually ...) double[] hsl = RGB2HSL(result); // values are in the range [0..100] (usually ...)
applyHslModOff(hsl, 0, color.getHueMod(), color.getHueOff()); applyHslModOff(hsl, 0, color.getHueMod(), color.getHueOff());
applyHslModOff(hsl, 1, color.getSatMod(), color.getSatOff()); applyHslModOff(hsl, 1, color.getSatMod(), color.getSatOff());
applyHslModOff(hsl, 2, color.getLumMod(), color.getLumOff()); applyHslModOff(hsl, 2, color.getLumMod(), color.getLumOff());
@ -344,7 +336,7 @@ public class DrawPaint {
* @param mod the modulation adjustment * @param mod the modulation adjustment
* @param off the offset adjustment * @param off the offset adjustment
*/ */
private static void applyHslModOff(double hsl[], int hslPart, int mod, int off) { private static void applyHslModOff(double[] hsl, int hslPart, int mod, int off) {
if (mod == -1) { if (mod == -1) {
mod = 100000; mod = 100000;
} }
@ -363,7 +355,7 @@ public class DrawPaint {
* *
* For a shade, the equation is luminance * %tint. * For a shade, the equation is luminance * %tint.
*/ */
private static void applyShade(double hsl[], ColorStyle fc) { private static void applyShade(double[] hsl, ColorStyle fc) {
int shade = fc.getShade(); int shade = fc.getShade();
if (shade == -1) { if (shade == -1) {
return; return;
@ -380,7 +372,7 @@ public class DrawPaint {
* For a tint, the equation is luminance * %tint + (1-%tint). * For a tint, the equation is luminance * %tint + (1-%tint).
* (Note that 1-%tint is equal to the lumOff value in DrawingML.) * (Note that 1-%tint is equal to the lumOff value in DrawingML.)
*/ */
private static void applyTint(double hsl[], ColorStyle fc) { private static void applyTint(double[] hsl, ColorStyle fc) {
int tint = fc.getTint(); int tint = fc.getTint();
if (tint == -1) { if (tint == -1) {
return; return;
@ -403,70 +395,63 @@ public class DrawPaint {
} }
Rectangle2D anchor = DrawShape.getAnchor(graphics, shape); Rectangle2D anchor = DrawShape.getAnchor(graphics, shape);
final double h = anchor.getHeight(), w = anchor.getWidth(), x = anchor.getX(), y = anchor.getY();
AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(angle), anchor.getCenterX(), anchor.getCenterY()); AffineTransform at = AffineTransform.getRotateInstance(Math.toRadians(angle), anchor.getCenterX(), anchor.getCenterY());
double diagonal = Math.sqrt(h * h + w * w); double diagonal = Math.sqrt(Math.pow(anchor.getWidth(),2) + Math.pow(anchor.getHeight(),2));
Point2D p1 = new Point2D.Double(x + w / 2 - diagonal / 2, y + h / 2); final Point2D p1 = at.transform(new Point2D.Double(anchor.getCenterX() - diagonal / 2, anchor.getCenterY()), null);
p1 = at.transform(p1, null); final Point2D p2 = at.transform(new Point2D.Double(anchor.getMaxX(), anchor.getCenterY()), null);
Point2D p2 = new Point2D.Double(x + w, y + h / 2);
p2 = at.transform(p2, null);
// snapToAnchor(p1, anchor); // snapToAnchor(p1, anchor);
// snapToAnchor(p2, anchor); // snapToAnchor(p2, anchor);
if (p1.equals(p2)) { // gradient paint on the same point throws an exception ... and doesn't make sense
// gradient paint on the same point throws an exception ... and doesn't make sense return (p1.equals(p2)) ? null : safeFractions((f,c)->new LinearGradientPaint(p1,p2,f,c), fill);
return null;
}
float[] fractions = fill.getGradientFractions();
Color[] colors = new Color[fractions.length];
int i = 0;
for (ColorStyle fc : fill.getGradientColors()) {
// if fc is null, use transparent color to get color of background
colors[i++] = (fc == null) ? TRANSPARENT : applyColorTransform(fc);
}
return new LinearGradientPaint(p1, p2, fractions, colors);
} }
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
protected Paint createRadialGradientPaint(GradientPaint fill, Graphics2D graphics) { protected Paint createRadialGradientPaint(GradientPaint fill, Graphics2D graphics) {
Rectangle2D anchor = DrawShape.getAnchor(graphics, shape); Rectangle2D anchor = DrawShape.getAnchor(graphics, shape);
Point2D pCenter = new Point2D.Double(anchor.getX() + anchor.getWidth()/2, final Point2D pCenter = new Point2D.Double(anchor.getCenterX(), anchor.getCenterY());
anchor.getY() + anchor.getHeight()/2);
float radius = (float)Math.max(anchor.getWidth(), anchor.getHeight()); final float radius = (float)Math.max(anchor.getWidth(), anchor.getHeight());
float[] fractions = fill.getGradientFractions(); return safeFractions((f,c)->new RadialGradientPaint(pCenter,radius,f,c), fill);
Color[] colors = new Color[fractions.length];
int i=0;
for (ColorStyle fc : fill.getGradientColors()) {
colors[i++] = applyColorTransform(fc);
}
return new RadialGradientPaint(pCenter, radius, fractions, colors);
} }
@SuppressWarnings({"WeakerAccess", "unused"}) @SuppressWarnings({"WeakerAccess", "unused"})
protected Paint createPathGradientPaint(GradientPaint fill, Graphics2D graphics) { protected Paint createPathGradientPaint(GradientPaint fill, Graphics2D graphics) {
// currently we ignore an eventually center setting // currently we ignore an eventually center setting
float[] fractions = fill.getGradientFractions(); return safeFractions(PathGradientPaint::new, fill);
Color[] colors = new Color[fractions.length]; }
int i=0; private Paint safeFractions(BiFunction<float[],Color[],Paint> init, GradientPaint fill) {
for (ColorStyle fc : fill.getGradientColors()) { float[] fractions = fill.getGradientFractions();
colors[i++] = applyColorTransform(fc); final ColorStyle[] styles = fill.getGradientColors();
// need to remap the fractions, because Java doesn't like repeating fraction values
Map<Float,Color> m = new TreeMap<>();
for (int i = 0; i<fractions.length; i++) {
// if fc is null, use transparent color to get color of background
m.put(fractions[i], (styles[i] == null ? TRANSPARENT : applyColorTransform(styles[i])));
} }
return new PathGradientPaint(colors, fractions); final Color[] colors = new Color[m.size()];
if (fractions.length != m.size()) {
fractions = new float[m.size()];
}
int i=0;
for (Map.Entry<Float,Color> me : m.entrySet()) {
fractions[i] = me.getKey();
colors[i] = me.getValue();
i++;
}
return init.apply(fractions, colors);
} }
/** /**

View File

@ -23,21 +23,24 @@ import java.awt.MultipleGradientPaint.CycleMethod;
import java.awt.geom.*; import java.awt.geom.*;
import java.awt.image.*; import java.awt.image.*;
import org.apache.poi.util.Internal;
@Internal
class PathGradientPaint implements Paint { class PathGradientPaint implements Paint {
// http://asserttrue.blogspot.de/2010/01/how-to-iimplement-custom-paint-in-50.html // http://asserttrue.blogspot.de/2010/01/how-to-iimplement-custom-paint-in-50.html
protected final Color colors[]; private final Color[] colors;
protected final float fractions[]; private final float[] fractions;
protected final int capStyle; private final int capStyle;
protected final int joinStyle; private final int joinStyle;
protected final int transparency; private final int transparency;
public PathGradientPaint(Color colors[], float fractions[]) { PathGradientPaint(float[] fractions, Color[] colors) {
this(colors,fractions,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND); this(fractions,colors,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
} }
public PathGradientPaint(Color colors[], float fractions[], int capStyle, int joinStyle) { private PathGradientPaint(float[] fractions, Color[] colors, int capStyle, int joinStyle) {
this.colors = colors.clone(); this.colors = colors.clone();
this.fractions = fractions.clone(); this.fractions = fractions.clone();
this.capStyle = capStyle; this.capStyle = capStyle;
@ -66,26 +69,26 @@ class PathGradientPaint implements Paint {
} }
class PathGradientContext implements PaintContext { class PathGradientContext implements PaintContext {
protected final Rectangle deviceBounds; final Rectangle deviceBounds;
protected final Rectangle2D userBounds; final Rectangle2D userBounds;
protected final AffineTransform xform; protected final AffineTransform xform;
protected final RenderingHints hints; final RenderingHints hints;
/** /**
* for POI: the shape will be only known when the subclasses determines the concrete implementation * for POI: the shape will be only known when the subclasses determines the concrete implementation
* in the draw/-content method, so we need to postpone the setting/creation as long as possible * in the draw/-content method, so we need to postpone the setting/creation as long as possible
**/ **/
protected final Shape shape; protected final Shape shape;
protected final PaintContext pCtx; final PaintContext pCtx;
protected final int gradientSteps; final int gradientSteps;
WritableRaster raster; WritableRaster raster;
public PathGradientContext( PathGradientContext(
ColorModel cm ColorModel cm
, Rectangle deviceBounds , Rectangle deviceBounds
, Rectangle2D userBounds , Rectangle2D userBounds
, AffineTransform xform , AffineTransform xform
, RenderingHints hints , RenderingHints hints
) { ) {
shape = (Shape)hints.get(Drawable.GRADIENT_SHAPE); shape = (Shape)hints.get(Drawable.GRADIENT_SHAPE);
if (shape == null) { if (shape == null) {
@ -139,7 +142,7 @@ class PathGradientPaint implements Paint {
return childRaster; return childRaster;
} }
protected int getGradientSteps(Shape gradientShape) { int getGradientSteps(Shape gradientShape) {
Rectangle rect = gradientShape.getBounds(); Rectangle rect = gradientShape.getBounds();
int lower = 1; int lower = 1;
int upper = (int)(Math.max(rect.getWidth(),rect.getHeight())/2.0); int upper = (int)(Math.max(rect.getWidth(),rect.getHeight())/2.0);
@ -158,7 +161,7 @@ class PathGradientPaint implements Paint {
protected void createRaster() { void createRaster() {
ColorModel cm = getColorModel(); ColorModel cm = getColorModel();
raster = cm.createCompatibleWritableRaster((int)deviceBounds.getWidth(), (int)deviceBounds.getHeight()); raster = cm.createCompatibleWritableRaster((int)deviceBounds.getWidth(), (int)deviceBounds.getHeight());
BufferedImage img = new BufferedImage(cm, raster, false, null); BufferedImage img = new BufferedImage(cm, raster, false, null);
@ -168,7 +171,7 @@ class PathGradientPaint implements Paint {
graphics.transform(xform); graphics.transform(xform);
Raster img2 = pCtx.getRaster(0, 0, gradientSteps, 1); Raster img2 = pCtx.getRaster(0, 0, gradientSteps, 1);
int rgb[] = new int[cm.getNumComponents()]; int[] rgb = new int[cm.getNumComponents()];
for (int i = gradientSteps-1; i>=0; i--) { for (int i = gradientSteps-1; i>=0; i--) {
img2.getPixel(i, 0, rgb); img2.getPixel(i, 0, rgb);

View File

@ -59,6 +59,7 @@ public final class SheetNameFormatter {
* @param rawSheetName - sheet name * @param rawSheetName - sheet name
* @deprecated use <code>appendFormat(StringBuilder out, String rawSheetName)</code> instead * @deprecated use <code>appendFormat(StringBuilder out, String rawSheetName)</code> instead
*/ */
@Deprecated
public static void appendFormat(StringBuffer out, String rawSheetName) { public static void appendFormat(StringBuffer out, String rawSheetName) {
boolean needsQuotes = needsDelimiting(rawSheetName); boolean needsQuotes = needsDelimiting(rawSheetName);
if(needsQuotes) { if(needsQuotes) {
@ -73,6 +74,7 @@ public final class SheetNameFormatter {
/** /**
* @deprecated use <code>appendFormat(StringBuilder out, String workbookName, String rawSheetName)</code> instead * @deprecated use <code>appendFormat(StringBuilder out, String workbookName, String rawSheetName)</code> instead
*/ */
@Deprecated
public static void appendFormat(StringBuffer out, String workbookName, String rawSheetName) { public static void appendFormat(StringBuffer out, String workbookName, String rawSheetName) {
boolean needsQuotes = needsDelimiting(workbookName) || needsDelimiting(rawSheetName); boolean needsQuotes = needsDelimiting(workbookName) || needsDelimiting(rawSheetName);
if(needsQuotes) { if(needsQuotes) {
@ -123,7 +125,7 @@ public final class SheetNameFormatter {
} }
} }
private static void appendAndEscape(Appendable sb, String rawSheetName) { static void appendAndEscape(Appendable sb, String rawSheetName) {
int len = rawSheetName.length(); int len = rawSheetName.length();
for(int i=0; i<len; i++) { for(int i=0; i<len; i++) {
char ch = rawSheetName.charAt(i); char ch = rawSheetName.charAt(i);
@ -139,7 +141,12 @@ public final class SheetNameFormatter {
} }
} }
private static boolean needsDelimiting(String rawSheetName) { /**
* Tell if the given raw sheet name needs screening/delimiting.
* @param rawSheetName the sheet name.
* @return true if the given raw sheet name needs screening/delimiting, false otherwise.
*/
static boolean needsDelimiting(String rawSheetName) {
int len = rawSheetName.length(); int len = rawSheetName.length();
if(len < 1) { if(len < 1) {
throw new RuntimeException("Zero length string is an invalid sheet name"); throw new RuntimeException("Zero length string is an invalid sheet name");

View File

@ -0,0 +1,73 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.ss.formula;
public class SheetRangeAndWorkbookIndexFormatter {
private SheetRangeAndWorkbookIndexFormatter() {
}
public static String format(StringBuilder sb, int workbookIndex, String firstSheetName, String lastSheetName) {
if (anySheetNameNeedsEscaping(firstSheetName, lastSheetName)) {
return formatWithDelimiting(sb, workbookIndex, firstSheetName, lastSheetName);
} else {
return formatWithoutDelimiting(sb, workbookIndex, firstSheetName, lastSheetName);
}
}
private static String formatWithDelimiting(StringBuilder sb, int workbookIndex, String firstSheetName, String lastSheetName) {
sb.append('\'');
if (workbookIndex >= 0) {
sb.append('[');
sb.append(workbookIndex);
sb.append(']');
}
SheetNameFormatter.appendAndEscape(sb, firstSheetName);
if (lastSheetName != null) {
sb.append(':');
SheetNameFormatter.appendAndEscape(sb, lastSheetName);
}
sb.append('\'');
return sb.toString();
}
private static String formatWithoutDelimiting(StringBuilder sb, int workbookIndex, String firstSheetName, String lastSheetName) {
if (workbookIndex >= 0) {
sb.append('[');
sb.append(workbookIndex);
sb.append(']');
}
sb.append(firstSheetName);
if (lastSheetName != null) {
sb.append(':');
sb.append(lastSheetName);
}
return sb.toString();
}
private static boolean anySheetNameNeedsEscaping(String firstSheetName, String lastSheetName) {
boolean anySheetNameNeedsDelimiting = firstSheetName != null && SheetNameFormatter.needsDelimiting(firstSheetName);
anySheetNameNeedsDelimiting |= lastSheetName != null && SheetNameFormatter.needsDelimiting(lastSheetName);
return anySheetNameNeedsDelimiting;
}
}

View File

@ -20,6 +20,7 @@ package org.apache.poi.ss.formula.ptg;
import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.formula.SheetIdentifier; import org.apache.poi.ss.formula.SheetIdentifier;
import org.apache.poi.ss.formula.SheetNameFormatter; import org.apache.poi.ss.formula.SheetNameFormatter;
import org.apache.poi.ss.formula.SheetRangeAndWorkbookIndexFormatter;
import org.apache.poi.ss.formula.SheetRangeIdentifier; import org.apache.poi.ss.formula.SheetRangeIdentifier;
import org.apache.poi.ss.util.AreaReference; import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
@ -102,16 +103,8 @@ public final class Area3DPxg extends AreaPtgBase implements Pxg3D {
public String toFormulaString() { public String toFormulaString() {
StringBuilder sb = new StringBuilder(64); StringBuilder sb = new StringBuilder(64);
if (externalWorkbookNumber >= 0) {
sb.append('['); SheetRangeAndWorkbookIndexFormatter.format(sb, externalWorkbookNumber, firstSheetName, lastSheetName);
sb.append(externalWorkbookNumber);
sb.append(']');
}
SheetNameFormatter.appendFormat(sb, firstSheetName);
if (lastSheetName != null) {
sb.append(':');
SheetNameFormatter.appendFormat(sb, lastSheetName);
}
sb.append('!'); sb.append('!');
sb.append(formatReferenceAsString()); sb.append(formatReferenceAsString());
return sb.toString(); return sb.toString();

View File

@ -18,7 +18,7 @@
package org.apache.poi.ss.formula.ptg; package org.apache.poi.ss.formula.ptg;
import org.apache.poi.ss.formula.SheetIdentifier; import org.apache.poi.ss.formula.SheetIdentifier;
import org.apache.poi.ss.formula.SheetNameFormatter; import org.apache.poi.ss.formula.SheetRangeAndWorkbookIndexFormatter;
import org.apache.poi.ss.formula.SheetRangeIdentifier; import org.apache.poi.ss.formula.SheetRangeIdentifier;
import org.apache.poi.ss.util.CellReference; import org.apache.poi.ss.util.CellReference;
import org.apache.poi.util.LittleEndianOutput; import org.apache.poi.util.LittleEndianOutput;
@ -101,18 +101,8 @@ public final class Ref3DPxg extends RefPtgBase implements Pxg3D {
public String toFormulaString() { public String toFormulaString() {
StringBuilder sb = new StringBuilder(64); StringBuilder sb = new StringBuilder(64);
if (externalWorkbookNumber >= 0) {
sb.append('['); SheetRangeAndWorkbookIndexFormatter.format(sb, externalWorkbookNumber, firstSheetName, lastSheetName);
sb.append(externalWorkbookNumber);
sb.append(']');
}
if (firstSheetName != null) {
SheetNameFormatter.appendFormat(sb, firstSheetName);
}
if (lastSheetName != null) {
sb.append(':');
SheetNameFormatter.appendFormat(sb, lastSheetName);
}
sb.append('!'); sb.append('!');
sb.append(formatReferenceAsString()); sb.append(formatReferenceAsString());
return sb.toString(); return sb.toString();

View File

@ -45,8 +45,8 @@ public class RecordFormatException
* be thrown. If assertTrue is <code>false</code>, this will throw this * be thrown. If assertTrue is <code>false</code>, this will throw this
* exception with the message. * exception with the message.
* *
* @param assertTrue * @param assertTrue If false, the exception is thrown, if true, no action is performed
* @param message * @param message The message to include in the thrown exception
*/ */
public static void check(boolean assertTrue, String message) { public static void check(boolean assertTrue, String message) {
if (! assertTrue) { if (! assertTrue) {

View File

@ -615,7 +615,7 @@ public class POIXMLDocumentPart {
protected void read(POIXMLFactory factory, Map<PackagePart, POIXMLDocumentPart> context) throws OpenXML4JException { protected void read(POIXMLFactory factory, Map<PackagePart, POIXMLDocumentPart> context) throws OpenXML4JException {
PackagePart pp = getPackagePart(); PackagePart pp = getPackagePart();
if (pp.getContentType().equals(XWPFRelation.TEMPLATE.getContentType())) { if (pp.getContentType().equals(XWPFRelation.GLOSSARY_DOCUMENT.getContentType())) {
logger.log(POILogger.WARN, logger.log(POILogger.WARN,
"POI does not currently support template.main+xml (glossary) parts. " + "POI does not currently support template.main+xml (glossary) parts. " +
"Skipping this part for now."); "Skipping this part for now.");

View File

@ -22,41 +22,37 @@ import org.apache.poi.extractor.POITextExtractor;
/** /**
* A command line wrapper around {@link ExtractorFactory}, useful * A command line wrapper around {@link ExtractorFactory}, useful
* for when debugging. * for when debugging.
*/ */
public class CommandLineTextExtractor { public class CommandLineTextExtractor {
public static final String DIVIDER = "======================="; public static final String DIVIDER = "=======================";
public static void main(String[] args) throws Exception {
if(args.length < 1) {
System.err.println("Use:");
System.err.println(" CommandLineTextExtractor <filename> [filename] [filename]");
System.exit(1);
}
for (String arg : args) { public static void main(String[] args) throws Exception {
System.out.println(DIVIDER); if (args.length < 1) {
System.err.println("Use:");
System.err.println(" CommandLineTextExtractor <filename> [filename] [filename]");
System.exit(1);
}
File f = new File(arg); for (String arg : args) {
System.out.println(f); System.out.println(DIVIDER);
POITextExtractor extractor = File f = new File(arg);
ExtractorFactory.createExtractor(f); System.out.println(f);
try {
POITextExtractor metadataExtractor =
extractor.getMetadataTextExtractor();
System.out.println(" " + DIVIDER); try (POITextExtractor extractor = ExtractorFactory.createExtractor(f)) {
String metaData = metadataExtractor.getText(); POITextExtractor metadataExtractor =
System.out.println(metaData); extractor.getMetadataTextExtractor();
System.out.println(" " + DIVIDER);
String text = extractor.getText(); System.out.println(" " + DIVIDER);
System.out.println(text); String metaData = metadataExtractor.getText();
System.out.println(DIVIDER); System.out.println(metaData);
System.out.println("Had " + metaData.length() + " characters of metadata and " + text.length() + " characters of text"); System.out.println(" " + DIVIDER);
} finally { String text = extractor.getText();
extractor.close(); System.out.println(text);
} System.out.println(DIVIDER);
} System.out.println("Had " + metaData.length() + " characters of metadata and " + text.length() + " characters of text");
} }
}
}
} }

View File

@ -154,8 +154,6 @@ public final class ZipHelper {
"The supplied data appears to be a raw XML file. " + "The supplied data appears to be a raw XML file. " +
"Formats such as Office 2003 XML are not supported"); "Formats such as Office 2003 XML are not supported");
default: default:
case OOXML:
case UNKNOWN:
// Don't check for a Zip header, as to maintain backwards // Don't check for a Zip header, as to maintain backwards
// compatibility we need to let them seek over junk at the // compatibility we need to let them seek over junk at the
// start before beginning processing. // start before beginning processing.

View File

@ -38,7 +38,7 @@ public class ZipInputStreamZipEntrySource implements ZipEntrySource {
/** /**
* Reads all the entries from the ZipInputStream * Reads all the entries from the ZipInputStream
* into memory, and closes the source stream. * into memory, and don't close (since POI 4.0.1) the source stream.
* We'll then eat lots of memory, but be able to * We'll then eat lots of memory, but be able to
* work with the entries at-will. * work with the entries at-will.
*/ */
@ -50,7 +50,6 @@ public class ZipInputStreamZipEntrySource implements ZipEntrySource {
} }
zipEntries.put(zipEntry.getName(), new ZipArchiveFakeEntry(zipEntry, inp)); zipEntries.put(zipEntry.getName(), new ZipArchiveFakeEntry(zipEntry, inp));
} }
inp.close();
} }
@Override @Override

View File

@ -170,16 +170,24 @@ public class XSLFPictureShape extends XSLFSimpleShape
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
protected String getBlipLink(){ protected String getBlipLink(){
String link = getBlip().getLink(); CTBlip blip = getBlip();
if (link.isEmpty()) return null; if (blip != null) {
return link; String link = blip.getLink();
return (link.isEmpty()) ? null : link;
} else {
return null;
}
} }
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
protected String getBlipId(){ protected String getBlipId(){
String id = getBlip().getEmbed(); CTBlip blip = getBlip();
if (id.isEmpty()) return null; if (blip != null) {
return id; String id = blip.getEmbed();
return (id.isEmpty()) ? null : id;
} else {
return null;
}
} }
@Override @Override

View File

@ -19,6 +19,7 @@ package org.apache.poi.ooxml;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
@ -89,7 +90,7 @@ public final class TestPOIXMLProperties {
XSSFWorkbook newWorkbook = XSSFWorkbook newWorkbook =
XSSFTestDataSamples.writeOutAndReadBack(workbook); XSSFTestDataSamples.writeOutAndReadBack(workbook);
workbook.close(); workbook.close();
assertTrue(workbook != newWorkbook); assertNotSame(workbook, newWorkbook);
POIXMLProperties newProps = newWorkbook.getProperties(); POIXMLProperties newProps = newWorkbook.getProperties();
@ -158,7 +159,7 @@ public final class TestPOIXMLProperties {
p = ctProps.getPropertyArray(3); p = ctProps.getPropertyArray(3);
assertEquals("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", p.getFmtid()); assertEquals("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", p.getFmtid());
assertEquals("test-4", p.getName()); assertEquals("test-4", p.getName());
assertEquals(true, p.getBool()); assertTrue(p.getBool());
assertEquals(5, p.getPid()); assertEquals(5, p.getPid());
wb2.close(); wb2.close();

View File

@ -87,6 +87,10 @@ public class TestNecessaryOOXMLClasses {
Assert.assertNotNull(ctLblAlgn); Assert.assertNotNull(ctLblAlgn);
CTDashStopList ctDashStopList = CTDashStopList.Factory.newInstance(); CTDashStopList ctDashStopList = CTDashStopList.Factory.newInstance();
Assert.assertNotNull(ctDashStopList); Assert.assertNotNull(ctDashStopList);
STDispBlanksAs stDashBlanksAs = STDispBlanksAs.Factory.newInstance();
Assert.assertNotNull(stDashBlanksAs);
CTDispBlanksAs ctDashBlanksAs = CTDispBlanksAs.Factory.newInstance();
Assert.assertNotNull(ctDashBlanksAs);
STLblAlgn.Enum e1 = STLblAlgn.Enum.forString("ctr"); STLblAlgn.Enum e1 = STLblAlgn.Enum.forString("ctr");
Assert.assertNotNull(e1); Assert.assertNotNull(e1);
@ -100,6 +104,8 @@ public class TestNecessaryOOXMLClasses {
Assert.assertNotNull(e5); Assert.assertNotNull(e5);
STMarkerStyle.Enum e6 = STMarkerStyle.Enum.forString("circle"); STMarkerStyle.Enum e6 = STMarkerStyle.Enum.forString("circle");
Assert.assertNotNull(e6); Assert.assertNotNull(e6);
STDispBlanksAs.Enum e7 = STDispBlanksAs.Enum.forString("span");
Assert.assertNotNull(e7);
CTTextBulletTypefaceFollowText ctTextBulletTypefaceFollowText = CTTextBulletTypefaceFollowText.Factory.newInstance(); CTTextBulletTypefaceFollowText ctTextBulletTypefaceFollowText = CTTextBulletTypefaceFollowText.Factory.newInstance();
Assert.assertNotNull(ctTextBulletTypefaceFollowText); Assert.assertNotNull(ctTextBulletTypefaceFollowText);

View File

@ -42,7 +42,7 @@ public class TestXDGFVisioExtractor {
} }
@After @After
public void closeResoures() throws IOException { public void closeResources() throws IOException {
if(xml != null) { if(xml != null) {
xml.close(); xml.close();
} }

View File

@ -17,12 +17,7 @@
package org.apache.poi.xslf; package org.apache.poi.xslf;
import static org.apache.poi.POITestCase.assertContains; import static org.apache.poi.POITestCase.assertContains;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.awt.Color; import java.awt.Color;
import java.awt.Dimension; import java.awt.Dimension;
@ -93,6 +88,25 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTShape;
public class TestXSLFBugs { public class TestXSLFBugs {
private static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance(); private static final POIDataSamples slTests = POIDataSamples.getSlideShowInstance();
@Test
public void bug62929() throws Exception {
try(XMLSlideShow ss1 = XSLFTestDataSamples.openSampleDocument("missing-blip-fill.pptx")) {
assertEquals(1, ss1.getSlides().size());
XSLFSlide slide = ss1.getSlides().get(0);
assertEquals(slide.getShapes().size(), 1);
XSLFPictureShape picture = (XSLFPictureShape)slide.getShapes().get(0);
assertEquals(picture.getShapeId(), 662);
assertFalse(picture.isExternalLinkedPicture());
assertNull(picture.getPictureData());
assertNull(picture.getPictureLink());
assertNull(picture.getClipping());
}
}
@Test @Test
public void bug62736() throws Exception { public void bug62736() throws Exception {
XMLSlideShow ss1 = XSLFTestDataSamples.openSampleDocument("bug62736.pptx"); XMLSlideShow ss1 = XSLFTestDataSamples.openSampleDocument("bug62736.pptx");

View File

@ -47,7 +47,7 @@ public class TestPPTX2PNG {
private static final POIDataSamples samples = POIDataSamples.getSlideShowInstance(); private static final POIDataSamples samples = POIDataSamples.getSlideShowInstance();
private static final File basedir = null; private static final File basedir = null;
private static final String files = private static final String files =
"53446.ppt, alterman_security.ppt, alterman_security.pptx, KEY02.pptx, themes.pptx, backgrounds.pptx, layouts.pptx, sample.pptx, shapes.pptx, 54880_chinese.ppt"; "53446.ppt, alterman_security.ppt, alterman_security.pptx, KEY02.pptx, themes.pptx, backgrounds.pptx, layouts.pptx, sample.pptx, shapes.pptx, 54880_chinese.ppt, keyframes.pptx";

View File

@ -70,7 +70,7 @@ public class XSSFTestDataSamples {
* @param wb the workbook to write * @param wb the workbook to write
* @param testName a fragment of the filename * @param testName a fragment of the filename
* @return the location where the workbook was saved * @return the location where the workbook was saved
* @throws IOException * @throws IOException If writing the file fails
*/ */
public static <R extends Workbook> File writeOut(R wb, String testName) throws IOException { public static <R extends Workbook> File writeOut(R wb, String testName) throws IOException {
final File file = getOutputFile(testName); final File file = getOutputFile(testName);
@ -104,7 +104,9 @@ public class XSSFTestDataSamples {
file = TempFile.createTempFile(testName, ".xlsx"); file = TempFile.createTempFile(testName, ".xlsx");
} }
if (file.exists()) { if (file.exists()) {
file.delete(); if(!file.delete()) {
throw new IOException("Could not delete file " + file);
}
} }
return file; return file;
} }
@ -114,7 +116,7 @@ public class XSSFTestDataSamples {
* *
* @param wb the workbook to write * @param wb the workbook to write
* @return the memory buffer * @return the memory buffer
* @throws IOException * @throws IOException If writing the file fails
*/ */
public static <R extends Workbook> ByteArrayOutputStream writeOut(R wb) throws IOException { public static <R extends Workbook> ByteArrayOutputStream writeOut(R wb) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(8192); ByteArrayOutputStream out = new ByteArrayOutputStream(8192);
@ -137,7 +139,7 @@ public class XSSFTestDataSamples {
* to avoid creating a temporary file. However, this may complicate the calling * to avoid creating a temporary file. However, this may complicate the calling
* code to avoid having the workbook, BAOS, and BAIS open at the same time. * code to avoid having the workbook, BAOS, and BAIS open at the same time.
* *
* @param wb * @param wb The workbook to write out, it is closed after the call.
* @param testName file name to be used to write to a file. This file will be cleaned up by a call to readBack(String) * @param testName file name to be used to write to a file. This file will be cleaned up by a call to readBack(String)
* @return workbook location * @return workbook location
* @throws RuntimeException if {@link #TEST_OUTPUT_DIR} System property is not set * @throws RuntimeException if {@link #TEST_OUTPUT_DIR} System property is not set
@ -161,18 +163,13 @@ public class XSSFTestDataSamples {
* *
* @param wb the workbook to write * @param wb the workbook to write
* @return the memory buffer * @return the memory buffer
* @throws IOException * @throws RuntimeException If writing the file fails
*/ */
public static <R extends Workbook> ByteArrayOutputStream writeOutAndClose(R wb) { public static <R extends Workbook> ByteArrayOutputStream writeOutAndClose(R wb) throws IOException {
try { ByteArrayOutputStream out = writeOut(wb);
ByteArrayOutputStream out = writeOut(wb); // Do not close the workbook if there was a problem writing the workbook
// Do not close the workbook if there was a problem writing the workbook wb.close();
wb.close(); return out;
return out;
}
catch (final IOException e) {
throw new RuntimeException(e);
}
} }
/** /**
@ -183,12 +180,14 @@ public class XSSFTestDataSamples {
* *
* @param file the workbook file to read and delete * @param file the workbook file to read and delete
* @return the read back workbook * @return the read back workbook
* @throws IOException * @throws IOException If reading or deleting the file fails
*/ */
public static XSSFWorkbook readBackAndDelete(File file) throws IOException { public static XSSFWorkbook readBackAndDelete(File file) throws IOException {
XSSFWorkbook wb = readBack(file); XSSFWorkbook wb = readBack(file);
// do not delete the file if there's an error--might be helpful for debugging // do not delete the file if there's an error--might be helpful for debugging
file.delete(); if(!file.delete()) {
throw new IOException("Could not delete file " + file + " after reading");
}
return wb; return wb;
} }
@ -198,16 +197,12 @@ public class XSSFTestDataSamples {
* *
* @param file the workbook file to read * @param file the workbook file to read
* @return the read back workbook * @return the read back workbook
* @throws IOException * @throws IOException If reading the file fails
*/ */
public static XSSFWorkbook readBack(File file) throws IOException { public static XSSFWorkbook readBack(File file) throws IOException {
InputStream in = new FileInputStream(file); try (InputStream in = new FileInputStream(file)) {
try {
return new XSSFWorkbook(in); return new XSSFWorkbook(in);
} }
finally {
in.close();
}
} }
/** /**
@ -216,17 +211,13 @@ public class XSSFTestDataSamples {
* *
* @param out the output stream to read back from * @param out the output stream to read back from
* @return the read back workbook * @return the read back workbook
* @throws IOException * @throws IOException If reading the file fails
*/ */
public static XSSFWorkbook readBack(ByteArrayOutputStream out) throws IOException { public static XSSFWorkbook readBack(ByteArrayOutputStream out) throws IOException {
InputStream is = new ByteArrayInputStream(out.toByteArray()); try (InputStream is = new ByteArrayInputStream(out.toByteArray())) {
out.close(); out.close();
try {
return new XSSFWorkbook(is); return new XSSFWorkbook(is);
} }
finally {
is.close();
}
} }
/** /**

View File

@ -452,4 +452,12 @@ public class TestXWPFWordExtractor extends TestCase {
//once we add processing for this, we can change this to contains //once we add processing for this, we can change this to contains
assertNotContained(txt, "table rows"); assertNotContained(txt, "table rows");
} }
public void testPartsInTemplate() throws IOException {
XWPFDocument doc = XWPFTestDataSamples.openSampleDocument("60316b.dotx");
XWPFWordExtractor extractor = new XWPFWordExtractor(doc);
String txt = extractor.getText();
assertContains(txt, "header 2");
assertContains(txt, "footer 1");
}
} }

View File

@ -20,6 +20,8 @@
package org.apache.poi.hslf.record; package org.apache.poi.hslf.record;
import static org.apache.poi.hslf.usermodel.HSLFSlideShow.PP95_DOCUMENT;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
@ -143,7 +145,7 @@ public class CurrentUserAtom
// See how long it is. If it's under 28 bytes long, we can't // See how long it is. If it's under 28 bytes long, we can't
// read it // read it
if(_contents.length < 28) { if(_contents.length < 28) {
boolean isPP95 = dir.hasEntry("PP40"); boolean isPP95 = dir.hasEntry(PP95_DOCUMENT);
// PPT95 has 4 byte size, then data // PPT95 has 4 byte size, then data
if (!isPP95 && _contents.length >= 4) { if (!isPP95 && _contents.length >= 4) {
int size = LittleEndian.getInt(_contents); int size = LittleEndian.getInt(_contents);

View File

@ -71,6 +71,7 @@ public final class HSLFSlideShow implements SlideShow<HSLFShape,HSLFTextParagrap
/** Powerpoint document entry/stream name */ /** Powerpoint document entry/stream name */
public static final String POWERPOINT_DOCUMENT = "PowerPoint Document"; public static final String POWERPOINT_DOCUMENT = "PowerPoint Document";
public static final String PP95_DOCUMENT = "PP40";
enum LoadSavePhase { enum LoadSavePhase {
INIT, LOADED INIT, LOADED

View File

@ -17,6 +17,9 @@
package org.apache.poi.hslf.usermodel; package org.apache.poi.hslf.usermodel;
import static org.apache.poi.hslf.usermodel.HSLFSlideShow.POWERPOINT_DOCUMENT;
import static org.apache.poi.hslf.usermodel.HSLFSlideShow.PP95_DOCUMENT;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.Closeable; import java.io.Closeable;
@ -35,6 +38,7 @@ import java.util.TreeMap;
import org.apache.poi.POIDocument; import org.apache.poi.POIDocument;
import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException; import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException;
import org.apache.poi.hslf.exceptions.HSLFException; import org.apache.poi.hslf.exceptions.HSLFException;
import org.apache.poi.hslf.exceptions.OldPowerPointFormatException;
import org.apache.poi.hslf.record.CurrentUserAtom; import org.apache.poi.hslf.record.CurrentUserAtom;
import org.apache.poi.hslf.record.DocumentEncryptionAtom; import org.apache.poi.hslf.record.DocumentEncryptionAtom;
import org.apache.poi.hslf.record.ExOleObjStg; import org.apache.poi.hslf.record.ExOleObjStg;
@ -183,13 +187,18 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
* @throws IOException when the powerpoint can't be read * @throws IOException when the powerpoint can't be read
*/ */
private void readPowerPointStream() throws IOException { private void readPowerPointStream() throws IOException {
final DirectoryNode dir = getDirectory();
if (!dir.hasEntry(POWERPOINT_DOCUMENT) && dir.hasEntry(PP95_DOCUMENT)) {
throw new OldPowerPointFormatException("You seem to have supplied a PowerPoint95 file, which isn't supported");
}
// Get the main document stream // Get the main document stream
DocumentEntry docProps = DocumentEntry docProps = (DocumentEntry)dir.getEntry(POWERPOINT_DOCUMENT);
(DocumentEntry) getDirectory().getEntry(HSLFSlideShow.POWERPOINT_DOCUMENT);
// Grab the document stream // Grab the document stream
int len = docProps.getSize(); int len = docProps.getSize();
try (InputStream is = getDirectory().createDocumentInputStream(HSLFSlideShow.POWERPOINT_DOCUMENT)) { try (InputStream is = dir.createDocumentInputStream(docProps)) {
_docstream = IOUtils.toByteArray(is, len); _docstream = IOUtils.toByteArray(is, len);
} }
} }
@ -665,8 +674,8 @@ public final class HSLFSlideShowImpl extends POIDocument implements Closeable {
// Write the PPT stream into the POIFS layer // Write the PPT stream into the POIFS layer
ByteArrayInputStream bais = new ByteArrayInputStream(_docstream); ByteArrayInputStream bais = new ByteArrayInputStream(_docstream);
outFS.createOrUpdateDocument(bais, HSLFSlideShow.POWERPOINT_DOCUMENT); outFS.createOrUpdateDocument(bais, POWERPOINT_DOCUMENT);
writtenEntries.add(HSLFSlideShow.POWERPOINT_DOCUMENT); writtenEntries.add(POWERPOINT_DOCUMENT);
currentUser.setEncrypted(encryptedSS.getDocumentEncryptionAtom() != null); currentUser.setEncrypted(encryptedSS.getDocumentEncryptionAtom() != null);
currentUser.writeToFS(outFS); currentUser.writeToFS(outFS);

View File

@ -0,0 +1,81 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.poifs.filesystem;
import org.apache.commons.codec.Charsets;
import org.apache.poi.POIDataSamples;
import org.junit.Test;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import static org.junit.Assert.*;
public class TestFileMagic {
@Test
public void testFileMagic() {
assertEquals(FileMagic.XML, FileMagic.valueOf("XML"));
assertEquals(FileMagic.XML, FileMagic.valueOf("<?xml".getBytes(Charsets.UTF_8)));
assertEquals(FileMagic.HTML, FileMagic.valueOf("HTML"));
assertEquals(FileMagic.HTML, FileMagic.valueOf("<!DOCTYP".getBytes(Charsets.UTF_8)));
assertEquals(FileMagic.HTML, FileMagic.valueOf("<!DOCTYPE".getBytes(Charsets.UTF_8)));
assertEquals(FileMagic.HTML, FileMagic.valueOf("<html".getBytes(Charsets.UTF_8)));
try {
FileMagic.valueOf("some string");
fail("Should catch exception here");
} catch (IllegalArgumentException e) {
// expected here
}
}
@Test
public void testFileMagicFile() throws IOException {
assertEquals(FileMagic.OLE2, FileMagic.valueOf(POIDataSamples.getSpreadSheetInstance().getFile("SampleSS.xls")));
assertEquals(FileMagic.OOXML, FileMagic.valueOf(POIDataSamples.getSpreadSheetInstance().getFile("SampleSS.xlsx")));
}
@Test
public void testFileMagicStream() throws IOException {
try (InputStream stream = new BufferedInputStream(new FileInputStream(POIDataSamples.getSpreadSheetInstance().getFile("SampleSS.xls")))) {
assertEquals(FileMagic.OLE2, FileMagic.valueOf(stream));
}
try (InputStream stream = new BufferedInputStream(new FileInputStream(POIDataSamples.getSpreadSheetInstance().getFile("SampleSS.xlsx")))) {
assertEquals(FileMagic.OOXML, FileMagic.valueOf(stream));
}
}
@Test
public void testPrepare() throws IOException {
try (InputStream stream = new BufferedInputStream(new FileInputStream(POIDataSamples.getSpreadSheetInstance().getFile("SampleSS.xlsx")))) {
assertSame(stream, FileMagic.prepareToCheckMagic(stream));
}
try (InputStream stream = new InputStream() {
@Override
public int read() {
return 0;
}
}) {
assertNotSame(stream, FileMagic.prepareToCheckMagic(stream));
}
}
}

View File

@ -17,6 +17,7 @@
package org.apache.poi.poifs.filesystem; package org.apache.poi.poifs.filesystem;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
@ -278,4 +279,18 @@ public final class TestPOIFSFileSystem {
private static InputStream openSampleStream(String sampleFileName) { private static InputStream openSampleStream(String sampleFileName) {
return HSSFTestDataSamples.openSampleFileStream(sampleFileName); return HSSFTestDataSamples.openSampleFileStream(sampleFileName);
} }
@Test
public void fileMagics() {
for (FileMagic fm : FileMagic.values()) {
if (fm == FileMagic.UNKNOWN) {
continue;
}
for (byte[] b : fm.magic) {
assertEquals(fm, FileMagic.valueOf(b));
}
}
assertEquals(FileMagic.UNKNOWN, FileMagic.valueOf("foobaa".getBytes(UTF_8)));
}
} }

View File

@ -0,0 +1,66 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.ss.formula;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class SheetRangeAndWorkbookIndexFormatterTest {
@Test
public void noDelimiting_ifASingleSheetNameDoesntNeedDelimiting() {
StringBuilder sb = new StringBuilder();
String result = SheetRangeAndWorkbookIndexFormatter.format(sb, 0, "noDelimiting", null);
assertEquals("[0]noDelimiting", result);
}
@Test
public void everythingIsScreened_ifASingleSheetNameNeedsDelimiting() {
StringBuilder sb = new StringBuilder();
String result = SheetRangeAndWorkbookIndexFormatter.format(sb, 0, "1delimiting", null);
assertEquals("'[0]1delimiting'", result);
}
@Test
public void noDelimiting_ifBothSheetNamesDontNeedDelimiting() {
StringBuilder sb = new StringBuilder();
String result = SheetRangeAndWorkbookIndexFormatter.format(sb, 0, "noDelimiting1", "noDelimiting2");
assertEquals("[0]noDelimiting1:noDelimiting2", result);
}
@Test
public void everythingIsScreened_ifFirstSheetNamesNeedsDelimiting() {
StringBuilder sb = new StringBuilder();
String result = SheetRangeAndWorkbookIndexFormatter.format(sb, 0, "1delimiting", "noDelimiting");
assertEquals("'[0]1delimiting:noDelimiting'", result);
}
@Test
public void everythingIsScreened_ifLastSheetNamesNeedsDelimiting() {
StringBuilder sb = new StringBuilder();
String result = SheetRangeAndWorkbookIndexFormatter.format(sb, 0, "noDelimiting", "1delimiting");
assertEquals("'[0]noDelimiting:1delimiting'", result);
}
@Test
public void everythingIsScreened_ifBothSheetNamesNeedDelimiting() {
StringBuilder sb = new StringBuilder();
String result = SheetRangeAndWorkbookIndexFormatter.format(sb, 0, "1delimiting", "2delimiting");
assertEquals("'[0]1delimiting:2delimiting'", result);
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.