aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build.gradle8
-rw-r--r--build.xml16
-rw-r--r--osgi/pom.xml4
-rw-r--r--poi-examples/src/main/java/org/apache/poi/examples/xwpf/usermodel/SimpleImages.java26
-rw-r--r--poi-ooxml/build.gradle6
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/ooxml/util/NumberHelper.java2
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFChart.java2
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFChartData.java22
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/text/XDDFTextParagraph.java2
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xdgf/usermodel/XDGFShape.java3
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xssf/model/ThemesTable.java54
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/BaseXSSFEvaluationWorkbook.java8
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/BaseXSSFFormulaEvaluator.java2
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java7
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFTextParagraph.java7
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFTextRun.java4
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java55
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFAbstractFootnoteEndnote.java9
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFAbstractSDT.java5
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFComments.java6
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java4
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFHeaderFooter.java6
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFPictureData.java5
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFRun.java38
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFSDTCell.java10
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFSDTContentCell.java26
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTableCell.java23
-rw-r--r--poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTableRow.java3
-rw-r--r--poi-ooxml/src/test/java/org/apache/poi/xddf/usermodel/chart/TestXDDFChartRemoveSeries.java16
-rw-r--r--poi-ooxml/src/test/java/org/apache/poi/xssf/model/TestExternalLinksTable.java24
-rw-r--r--poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFPictureData.java2
-rw-r--r--poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java2
-rw-r--r--poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFComment.java3
-rw-r--r--poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFPictureData.java2
-rw-r--r--poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFRun.java39
-rw-r--r--poi/src/main/java/org/apache/poi/hssf/util/HSSFColor.java2
-rw-r--r--poi/src/main/java/org/apache/poi/poifs/dev/POIFSDump.java12
-rw-r--r--poi/src/main/java/org/apache/poi/poifs/macros/VBAMacroExtractor.java3
-rw-r--r--poi/src/main/java/org/apache/poi/poifs/property/PropertyTable.java13
-rw-r--r--poi/src/main/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java2
-rw-r--r--poi/src/main/java/org/apache/poi/ss/usermodel/DateUtil.java2
-rw-r--r--poi/src/main/java/org/apache/poi/ss/util/CellUtil.java2
-rw-r--r--poi/src/main/java/org/apache/poi/util/DefaultTempFileCreationStrategy.java2
-rw-r--r--poi/src/main/java/org/apache/poi/util/IOUtils.java23
-rw-r--r--poi/src/main/java/org/apache/poi/util/TempFile.java4
-rw-r--r--poi/src/test/java/org/apache/poi/util/TestIOUtils.java54
-rw-r--r--src/documentation/content/xdocs/changes.xml5
47 files changed, 398 insertions, 177 deletions
diff --git a/build.gradle b/build.gradle
index 6856adf9c8..7040561247 100644
--- a/build.gradle
+++ b/build.gradle
@@ -67,7 +67,7 @@ configurations {
}
dependencies {
- antLibs("org.junit.jupiter:junit-jupiter:5.13.3")
+ antLibs("org.junit.jupiter:junit-jupiter:5.13.4")
antLibs("org.apache.ant:ant-junitlauncher:1.10.15")
}
@@ -89,7 +89,7 @@ allprojects {
// apply plugin: 'eclipse'
apply plugin: 'idea'
- version = '5.4.2-SNAPSHOT'
+ version = '5.5.0-SNAPSHOT'
}
/**
@@ -108,11 +108,11 @@ subprojects {
ext {
bouncyCastleVersion = '1.81'
- commonsCodecVersion = '1.18.0'
+ commonsCodecVersion = '1.19.0'
commonsCompressVersion = '1.27.1'
commonsIoVersion = '2.20.0'
commonsMathVersion = '3.6.1'
- junitVersion = '5.13.3'
+ junitVersion = '5.13.4'
log4jVersion = '2.24.3'
mockitoVersion = '4.11.0'
hamcrestVersion = '3.0'
diff --git a/build.xml b/build.xml
index bc41fe5a69..2b40ac2cb9 100644
--- a/build.xml
+++ b/build.xml
@@ -42,7 +42,7 @@ under the License.
<description>The Apache POI project Ant build.</description>
- <property name="version.id" value="5.4.2-SNAPSHOT"/>
+ <property name="version.id" value="5.5.0-SNAPSHOT"/>
<property name="release.rc" value=""/>
<property environment="env"/>
@@ -263,21 +263,21 @@ under the License.
<!-- jars in the /lib directory, see the fetch-jars target-->
- <dependency prefix="main.commons-codec" artifact="commons-codec:commons-codec:1.18.0" usage="main"/>
+ <dependency prefix="main.commons-codec" artifact="commons-codec:commons-codec:1.19.0" usage="main"/>
<dependency prefix="main.commons-collections4" artifact="org.apache.commons:commons-collections4:4.5.0" usage="main"/>
<dependency prefix="main.commons-math3" artifact="org.apache.commons:commons-math3:3.6.1" usage="main"/>
<dependency prefix="main.commons-io" artifact="commons-io:commons-io:2.20.0" usage="main"/>
<dependency prefix="main.com.zaxxer" artifact="com.zaxxer:SparseBitSet:1.3" usage="main"/>
<dependency prefix="main.log4j-api" artifact="org.apache.logging.log4j:log4j-api:2.24.3" usage="main"/>
- <dependency prefix="main.junit-api" artifact="org.junit.jupiter:junit-jupiter-api:5.13.3" usage="main-tests"/>
- <dependency prefix="main.junit-jengine" artifact="org.junit.jupiter:junit-jupiter-engine:5.13.3" usage="main-tests"/>
- <dependency prefix="main.junit-params" artifact="org.junit.jupiter:junit-jupiter-params:5.13.3" usage="main-tests"/>
+ <dependency prefix="main.junit-api" artifact="org.junit.jupiter:junit-jupiter-api:5.13.4" usage="main-tests"/>
+ <dependency prefix="main.junit-jengine" artifact="org.junit.jupiter:junit-jupiter-engine:5.13.4" usage="main-tests"/>
+ <dependency prefix="main.junit-params" artifact="org.junit.jupiter:junit-jupiter-params:5.13.4" usage="main-tests"/>
<dependency prefix="main.junit-opentest4j" artifact="org.opentest4j:opentest4j:1.2.0" usage="main-tests"/>
<dependency prefix="main.junit-apiguardian" artifact="org.apiguardian:apiguardian-api:1.1.2" usage="main-tests"/>
- <dependency prefix="main.junit-pcommons" artifact="org.junit.platform:junit-platform-commons:1.13.3" usage="main-tests"/>
- <dependency prefix="main.junit-pengine" artifact="org.junit.platform:junit-platform-engine:1.13.3" usage="main-tests"/>
- <dependency prefix="main.junit-plauncher" artifact="org.junit.platform:junit-platform-launcher:1.13.3" usage="main-tests"/>
+ <dependency prefix="main.junit-pcommons" artifact="org.junit.platform:junit-platform-commons:1.13.4" usage="main-tests"/>
+ <dependency prefix="main.junit-pengine" artifact="org.junit.platform:junit-platform-engine:1.13.4" usage="main-tests"/>
+ <dependency prefix="main.junit-plauncher" artifact="org.junit.platform:junit-platform-launcher:1.13.4" usage="main-tests"/>
<dependency prefix="main.jmh" artifact="org.openjdk.jmh:jmh-core:1.35" usage="main-tests"/>
diff --git a/osgi/pom.xml b/osgi/pom.xml
index 351b2e276d..ec71465a4f 100644
--- a/osgi/pom.xml
+++ b/osgi/pom.xml
@@ -24,12 +24,12 @@
<groupId>org.apache.poi</groupId>
<artifactId>poi-bundle</artifactId>
<packaging>bundle</packaging>
- <version>5.4.2-SNAPSHOT</version>
+ <version>5.5.0-SNAPSHOT</version>
<name>Apache POI OSGi bundle</name>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <poi.version>5.4.2-SNAPSHOT</poi.version>
+ <poi.version>5.5.0-SNAPSHOT</poi.version>
<pax.exam.version>4.14.0</pax.exam.version>
</properties>
diff --git a/poi-examples/src/main/java/org/apache/poi/examples/xwpf/usermodel/SimpleImages.java b/poi-examples/src/main/java/org/apache/poi/examples/xwpf/usermodel/SimpleImages.java
index 1f996cfd1f..0e4c5670c0 100644
--- a/poi-examples/src/main/java/org/apache/poi/examples/xwpf/usermodel/SimpleImages.java
+++ b/poi-examples/src/main/java/org/apache/poi/examples/xwpf/usermodel/SimpleImages.java
@@ -22,10 +22,10 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import org.apache.poi.common.usermodel.PictureType;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.BreakType;
-import org.apache.poi.xwpf.usermodel.Document;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
@@ -45,30 +45,30 @@ public final class SimpleImages {
XWPFRun r = p.createRun();
for (String imgFile : args) {
- int format;
+ PictureType format;
if (imgFile.endsWith(".emf")) {
- format = Document.PICTURE_TYPE_EMF;
+ format = PictureType.EMF;
} else if (imgFile.endsWith(".wmf")) {
- format = Document.PICTURE_TYPE_WMF;
+ format = PictureType.WMF;
} else if (imgFile.endsWith(".pict")) {
- format = Document.PICTURE_TYPE_PICT;
+ format = PictureType.PICT;
} else if (imgFile.endsWith(".jpeg") || imgFile.endsWith(".jpg")) {
- format = Document.PICTURE_TYPE_JPEG;
+ format = PictureType.JPEG;
} else if (imgFile.endsWith(".png")) {
- format = Document.PICTURE_TYPE_PNG;
+ format = PictureType.PNG;
} else if (imgFile.endsWith(".dib")) {
- format = Document.PICTURE_TYPE_DIB;
+ format = PictureType.DIB;
} else if (imgFile.endsWith(".gif")) {
- format = Document.PICTURE_TYPE_GIF;
+ format = PictureType.GIF;
} else if (imgFile.endsWith(".tiff")) {
- format = Document.PICTURE_TYPE_TIFF;
+ format = PictureType.TIFF;
} else if (imgFile.endsWith(".eps")) {
- format = Document.PICTURE_TYPE_EPS;
+ format = PictureType.EPS;
} else if (imgFile.endsWith(".bmp")) {
- format = Document.PICTURE_TYPE_BMP;
+ format = PictureType.BMP;
} else if (imgFile.endsWith(".wpg")) {
- format = Document.PICTURE_TYPE_WPG;
+ format = PictureType.WPG;
} else {
System.err.println("Unsupported picture: " + imgFile +
". Expected emf|wmf|pict|jpeg|png|dib|gif|tiff|eps|bmp|wpg");
diff --git a/poi-ooxml/build.gradle b/poi-ooxml/build.gradle
index 8a9309799b..c2ef234d37 100644
--- a/poi-ooxml/build.gradle
+++ b/poi-ooxml/build.gradle
@@ -58,6 +58,12 @@ dependencies {
api project(':poi-ooxml-full')
api project(path: ':poi-ooxml-full', configuration: 'archives')
+ // Can be very useful in local testing to comment out the 2 poi-ooxml-full lines above
+ // and uncomment the line below to use a pre-built version of poi-ooxml-full.
+ // Try to use the last release version of poi-ooxml-full. You might be unlucky if
+ // recent unreleased changes in poi-ooxml-full are needed.
+ // api "org.apache.poi:poi-ooxml-full:5.4.1"
+
api "org.apache.xmlbeans:xmlbeans:${xmlbeansVersion}"
api "org.apache.commons:commons-compress:${commonsCompressVersion}"
api "commons-io:commons-io:${commonsIoVersion}"
diff --git a/poi-ooxml/src/main/java/org/apache/poi/ooxml/util/NumberHelper.java b/poi-ooxml/src/main/java/org/apache/poi/ooxml/util/NumberHelper.java
index 6d4cd26474..dbb397c448 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/ooxml/util/NumberHelper.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/ooxml/util/NumberHelper.java
@@ -23,7 +23,7 @@ import org.apache.poi.util.Internal;
* Helper class for number related operations.
* <p>Note: This class is for internal POI usage only.</p>
*
- * @since POI 5.4.2
+ * @since POI 5.5.0
*/
@Internal
public class NumberHelper {
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFChart.java b/poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFChart.java
index bfbb775296..4bfb948589 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFChart.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFChart.java
@@ -688,7 +688,7 @@ public abstract class XDDFChart extends POIXMLDocumentPart implements TextContai
if (axes.isEmpty() && hasAxes()) {
parseAxes();
}
- return axes;
+ return Collections.unmodifiableList(axes);
}
private boolean hasAxes() {
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFChartData.java b/poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFChartData.java
index 1dc47d47a4..983ef4f138 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFChartData.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/chart/XDDFChartData.java
@@ -28,7 +28,6 @@ import org.apache.poi.logging.PoiLogManager;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.util.Beta;
import org.apache.poi.util.Internal;
-import org.apache.poi.util.Removal;
import org.apache.poi.xddf.usermodel.XDDFFillProperties;
import org.apache.poi.xddf.usermodel.XDDFLineProperties;
import org.apache.poi.xddf.usermodel.XDDFShapeProperties;
@@ -85,27 +84,6 @@ public abstract class XDDFChartData {
return valueAxes;
}
- /**
- * Calls to {@code getSeries().add(series)} or to {@code getSeries().remove(series)}
- * may corrupt the workbook.
- *
- * <p>
- * Instead, use the following methods:
- * <ul>
- * <li>{@link #getSeriesCount()}</li>
- * <li>{@link #getSeries(int)}</li>
- * <li>{@link #addSeries(XDDFDataSource,XDDFNumericalDataSource)}</li>
- * <li>{@link #removeSeries(int)}</li>
- * </ul>
- *
- * @deprecated since POI 4.1.1
- */
- @Deprecated
- @Removal(version = "5.3")
- public List<Series> getSeries() {
- return Collections.unmodifiableList(series);
- }
-
public final int getSeriesCount() {
return series.size();
}
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/text/XDDFTextParagraph.java b/poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/text/XDDFTextParagraph.java
index 2fad9ddbbe..9f8b581c80 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/text/XDDFTextParagraph.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xddf/usermodel/text/XDDFTextParagraph.java
@@ -113,7 +113,7 @@ public class XDDFTextParagraph implements Iterable<XDDFTextRun> {
}
public List<XDDFTextRun> getTextRuns() {
- return _runs;
+ return Collections.unmodifiableList(_runs);
}
@Override
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xdgf/usermodel/XDGFShape.java b/poi-ooxml/src/main/java/org/apache/poi/xdgf/usermodel/XDGFShape.java
index 25b3af8f93..02f05ad1c5 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xdgf/usermodel/XDGFShape.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xdgf/usermodel/XDGFShape.java
@@ -27,6 +27,7 @@ import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Map.Entry;
@@ -307,7 +308,7 @@ public class XDGFShape extends XDGFSheet {
*/
// -> May be null
public List<XDGFShape> getShapes() {
- return _shapes;
+ return _shapes == null ? null : Collections.unmodifiableList(_shapes);
}
// unique to this shape on the page?
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/model/ThemesTable.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/model/ThemesTable.java
index 7bd391a06b..4d6655d5fc 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xssf/model/ThemesTable.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/model/ThemesTable.java
@@ -36,32 +36,34 @@ import org.openxmlformats.schemas.drawingml.x2006.main.ThemeDocument;
* colors and fonts.
*/
public class ThemesTable extends POIXMLDocumentPart implements Themes {
- public enum ThemeElement {
- LT1(0, "Lt1"),
- DK1(1,"Dk1"),
- LT2(2,"Lt2"),
- DK2(3,"Dk2"),
- ACCENT1(4,"Accent1"),
- ACCENT2(5,"Accent2"),
- ACCENT3(6,"Accent3"),
- ACCENT4(7,"Accent4"),
- ACCENT5(8,"Accent5"),
- ACCENT6(9,"Accent6"),
- HLINK(10,"Hlink"),
- FOLHLINK(11,"FolHlink"),
- UNKNOWN(-1,null);
-
- public static ThemeElement byId(int idx) {
- if (idx >= values().length || idx < 0) return UNKNOWN;
- return values()[idx];
- }
- ThemeElement(int idx, String name) {
- this.idx = idx;
- this.name = name;
- }
- public final int idx;
- public final String name;
- }
+ public enum ThemeElement {
+ LT1(0, "Lt1"),
+ DK1(1, "Dk1"),
+ LT2(2, "Lt2"),
+ DK2(3, "Dk2"),
+ ACCENT1(4, "Accent1"),
+ ACCENT2(5, "Accent2"),
+ ACCENT3(6, "Accent3"),
+ ACCENT4(7, "Accent4"),
+ ACCENT5(8, "Accent5"),
+ ACCENT6(9, "Accent6"),
+ HLINK(10, "Hlink"),
+ FOLHLINK(11, "FolHlink"),
+ UNKNOWN(-1, null);
+
+ public static ThemeElement byId(int idx) {
+ if (idx >= values().length || idx < 0) return UNKNOWN;
+ return values()[idx];
+ }
+
+ ThemeElement(int idx, String name) {
+ this.idx = idx;
+ this.name = name;
+ }
+
+ public final int idx;
+ public final String name;
+ }
private IndexedColorMap colorMap;
private ThemeDocument theme;
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/BaseXSSFEvaluationWorkbook.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/BaseXSSFEvaluationWorkbook.java
index 206ed84e49..c4a4673571 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/BaseXSSFEvaluationWorkbook.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/BaseXSSFEvaluationWorkbook.java
@@ -109,7 +109,7 @@ public abstract class BaseXSSFEvaluationWorkbook implements FormulaRenderingWork
} catch (NumberFormatException e) {}
// Look up an External Link Table for this name
- List<ExternalLinksTable> tables = _uBook.getExternalLinksTable();
+ List<ExternalLinksTable> tables = _uBook.getExternalLinksTables();
int index = findExternalLinkIndex(bookName, tables);
if (index != -1) return index;
@@ -126,7 +126,7 @@ public abstract class BaseXSSFEvaluationWorkbook implements FormulaRenderingWork
// So, add the missing reference and return
// Note - this is really rather nasty...
ExternalLinksTable fakeLinkTable = new FakeExternalLinksTable(relBookName);
- tables.add(fakeLinkTable);
+ _uBook.addExternalLinksTable(fakeLinkTable);
return tables.size(); // 1 based results, 0 = current workbook
}
@@ -193,7 +193,7 @@ public abstract class BaseXSSFEvaluationWorkbook implements FormulaRenderingWork
if (externalWorkbookNumber > 0) {
// External reference - reference is 1 based, link table is 0 based
int linkNumber = externalWorkbookNumber - 1;
- ExternalLinksTable linkTable = _uBook.getExternalLinksTable().get(linkNumber);
+ ExternalLinksTable linkTable = _uBook.getExternalLinksTable(linkNumber);
for (org.apache.poi.ss.usermodel.Name name : linkTable.getDefinedNames()) {
if (name.getNameName().equals(nameName)) {
@@ -300,7 +300,7 @@ public abstract class BaseXSSFEvaluationWorkbook implements FormulaRenderingWork
if (externalWorkbookNumber > 0) {
// External reference - reference is 1 based, link table is 0 based
int linkNumber = externalWorkbookNumber - 1;
- ExternalLinksTable linkTable = _uBook.getExternalLinksTable().get(linkNumber);
+ ExternalLinksTable linkTable = _uBook.getExternalLinksTable(linkNumber);
workbookName = linkTable.getLinkedFileName();
} else {
// Internal reference
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/BaseXSSFFormulaEvaluator.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/BaseXSSFFormulaEvaluator.java
index 3145e3f43c..b5674ada8e 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/BaseXSSFFormulaEvaluator.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/BaseXSSFFormulaEvaluator.java
@@ -128,7 +128,7 @@ public abstract class BaseXSSFFormulaEvaluator extends BaseFormulaEvaluator {
XSSFWorkbook xssfWorkbook = xssfCell.getSheet().getWorkbook();
XSSFWorkbook externalWorkbook = (XSSFWorkbook) xssfWorkbook.getCreationHelper()
.getReferencedWorkbooks().get(externalSheet.getWorkbookName());
- ExternalLinksTable externalLinksTable = xssfWorkbook.getExternalLinksTable().get(area3DPxg.getExternalWorkbookNumber() - 1);
+ ExternalLinksTable externalLinksTable = xssfWorkbook.getExternalLinksTable(area3DPxg.getExternalWorkbookNumber() - 1);
if (externalWorkbook != null && externalLinksTable != null) {
int firstSheet = externalWorkbook.getSheetIndex(area3DPxg.getSheetName());
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
index 5c67853c10..59cf488993 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
@@ -172,7 +172,7 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet, OoxmlSheetEx
tables.put( rp.getRelationship().getId(), (XSSFTable)p );
}
if(p instanceof XSSFPivotTable) {
- getWorkbook().getPivotTables().add((XSSFPivotTable) p);
+ getWorkbook().addPivotTable((XSSFPivotTable) p);
}
}
@@ -4705,13 +4705,12 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet, OoxmlSheetEx
@Beta
private XSSFPivotTable createPivotTable() {
XSSFWorkbook wb = getWorkbook();
- List<XSSFPivotTable> pivotTables = wb.getPivotTables();
int tableId = getWorkbook().getPivotTables().size()+1;
//Create relationship between pivotTable and the worksheet
XSSFPivotTable pivotTable = (XSSFPivotTable) createRelationship(XSSFRelation.PIVOT_TABLE,
getWorkbook().getXssfFactory(), tableId);
pivotTable.setParentSheet(this);
- pivotTables.add(pivotTable);
+ wb.addPivotTable(pivotTable);
XSSFWorkbook workbook = getWorkbook();
//Create relationship between the pivot cache definition and the workbook
@@ -4735,8 +4734,6 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet, OoxmlSheetEx
//Set relationships id for pivotCacheDefinition to pivotCacheRecords
pivotTable.getPivotCacheDefinition().getCTPivotCacheDefinition().setId(pivotCacheDefinition.getRelationId(pivotCacheRecords));
- wb.setPivotTables(pivotTables);
-
return pivotTable;
}
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFTextParagraph.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFTextParagraph.java
index db696efbf2..7f81c7dc77 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFTextParagraph.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFTextParagraph.java
@@ -19,6 +19,7 @@ package org.apache.poi.xssf.usermodel;
import java.awt.Color;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@@ -84,7 +85,7 @@ public class XSSFTextParagraph implements Iterable<XSSFTextRun>{
}
public List<XSSFTextRun> getTextRuns(){
- return _runs;
+ return Collections.unmodifiableList(_runs);
}
public Iterator<XSSFTextRun> iterator(){
@@ -268,7 +269,7 @@ public class XSSFTextParagraph implements Iterable<XSSFTextRun>{
*
* @return the color of bullet characters within a given paragraph.
* A <code>null</code> value means to use the text font color.
- * @since POI 5.4.2
+ * @since POI 5.5.0
*/
public byte[] getBulletFontColorAsBytes() {
ParagraphPropertyFetcher<byte[]> fetcher = new ParagraphPropertyFetcher<byte[]>(getLevel()) {
@@ -300,7 +301,7 @@ public class XSSFTextParagraph implements Iterable<XSSFTextRun>{
* Set the color to be used on bullet characters within a given paragraph.
*
* @param colorArray the bullet color (as byte array)
- * @since POI 5.4.2
+ * @since POI 5.5.0
*/
public void setBulletFontColor(byte[] colorArray) {
CTTextParagraphProperties pr = _p.isSetPPr() ? _p.getPPr() : _p.addNewPPr();
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFTextRun.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFTextRun.java
index ad460a5cc7..3789335a16 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFTextRun.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFTextRun.java
@@ -63,7 +63,7 @@ public class XSSFTextRun {
/**
* @param rgb
- * @since POI 5.4.2
+ * @since POI 5.5.0
*/
public void setFontColor(byte[] rgb) {
CTTextCharacterProperties rPr = getRPr();
@@ -89,7 +89,7 @@ public class XSSFTextRun {
/**
* @return the font color as a byte array.
- * @since POI 5.4.2
+ * @since POI 5.5.0
*/
public byte[] getFontColorAsBytes() {
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java
index 0c8ddce4a0..054a3dfb07 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java
@@ -205,7 +205,7 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Date1904Su
/**
* List of all pivot tables in workbook
*/
- private List<XSSFPivotTable> pivotTables;
+ private final List<XSSFPivotTable> pivotTables = new ArrayList<>();
private List<CTPivotCache> pivotCaches;
private final XSSFFactory xssfFactory;
@@ -386,7 +386,6 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Date1904Su
}
// Create arrays for parts attached to the workbook itself
- pivotTables = new ArrayList<>();
pivotCaches = new ArrayList<>();
}
@@ -524,7 +523,6 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Date1904Su
namedRanges = new ArrayList<>();
namedRangesByName = new ArrayListValuedHashMap<>();
sheets = new ArrayList<>();
- pivotTables = new ArrayList<>();
externalLinks = new ArrayList<>();
}
@@ -1042,14 +1040,14 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Date1904Su
*/
@Override
public List<XSSFPictureData> getAllPictures() {
- if(pictures == null){
+ if (pictures == null) {
List<PackagePart> mediaParts = getPackage().getPartsByName(GET_ALL_PICTURES_PATTERN);
pictures = new ArrayList<>(mediaParts.size());
for(PackagePart part : mediaParts){
pictures.add(new XSSFPictureData(part));
}
}
- return pictures; //YK: should return Collections.unmodifiableList(pictures);
+ return Collections.unmodifiableList(pictures);
}
/**
@@ -2079,11 +2077,46 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Date1904Su
* @return the {@code ExternalLinksTable} list, which may be empty
*/
@Internal
+ public List<ExternalLinksTable> getExternalLinksTables() {
+ // needs to be the live copy because unfortunately we don't have APIs to
+ // add and remove external links (this method is annotated @Internal)
+ return externalLinks;
+ }
+
+ @Deprecated // use getExternalLinksTables() instead
+ @Removal(version = "7.0.0")
+ @Internal
public List<ExternalLinksTable> getExternalLinksTable() {
+ // needs to be the live copy because unfortunately we don't have APIs to
+ // add and remove external links (this method is annotated @Internal)
return externalLinks;
}
/**
+ * Adds an External Links Table to the workbook.
+ *
+ * @param externalLinksTable the External Links Table to add
+ * @since POI 5.5.0
+ */
+ @Internal
+ public void addExternalLinksTable(ExternalLinksTable externalLinksTable) {
+ if (externalLinks == null) {
+ externalLinks = new ArrayList<>();
+ }
+ externalLinks.add(externalLinksTable);
+ }
+
+ /**
+ * @param index the index at which to add the External Links Table
+ * @return externalLinksTable the External Links Table to add
+ * @since POI 5.5.0
+ */
+ @Internal
+ public ExternalLinksTable getExternalLinksTable(int index) {
+ return externalLinks == null ? null : externalLinks.get(index);
+ }
+
+ /**
*
* @return a collection of custom XML mappings defined in this workbook
*/
@@ -2125,7 +2158,7 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Date1904Su
POIXMLDocumentPart.RelationPart rp = this.createRelationship(XSSFRelation.EXTERNAL_LINKS, xssfFactory, externalLinkIdx, false);
ExternalLinksTable linksTable = rp.getDocumentPart();
linksTable.setLinkedFileName(name);
- this.getExternalLinksTable().add(linksTable);
+ this.addExternalLinksTable(linksTable);
CTExternalReference ctExternalReference = this.getCTWorkbook().addNewExternalReferences().addNewExternalReference();
ctExternalReference.setId(rp.getRelationship().getId());
@@ -2385,7 +2418,7 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Date1904Su
}
CTPivotCache cache = caches.addNewPivotCache();
- int tableId = getPivotTables().size()+1;
+ final int tableId = pivotTables.size() + 1;
cache.setCacheId(tableId);
cache.setId(rId);
if(pivotCaches == null) {
@@ -2397,12 +2430,14 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook, Date1904Su
@Beta
public List<XSSFPivotTable> getPivotTables() {
+ // needs to be the live copy because unfortunately we don't have APIs to
+ // add and remove external links (this method is annotated @Beta)
return pivotTables;
}
- @Beta
- protected void setPivotTables(List<XSSFPivotTable> pivotTables) {
- this.pivotTables = pivotTables;
+ @Internal
+ public void addPivotTable(XSSFPivotTable pivotTable) {
+ pivotTables.add(pivotTable);
}
public XSSFWorkbookType getWorkbookType() {
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFAbstractFootnoteEndnote.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFAbstractFootnoteEndnote.java
index d924dcfef7..443aa598b9 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFAbstractFootnoteEndnote.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFAbstractFootnoteEndnote.java
@@ -18,6 +18,7 @@ package org.apache.poi.xwpf.usermodel;
import java.math.BigInteger;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Spliterator;
@@ -101,7 +102,7 @@ public abstract class XWPFAbstractFootnoteEndnote implements Iterable<XWPFParag
*/
@Override
public List<XWPFParagraph> getParagraphs() {
- return paragraphs;
+ return Collections.unmodifiableList(paragraphs);
}
/**
@@ -130,7 +131,7 @@ public abstract class XWPFAbstractFootnoteEndnote implements Iterable<XWPFParag
*/
@Override
public List<XWPFTable> getTables() {
- return tables;
+ return Collections.unmodifiableList(tables);
}
/**
@@ -138,7 +139,7 @@ public abstract class XWPFAbstractFootnoteEndnote implements Iterable<XWPFParag
* @return List of pictures
*/
public List<XWPFPictureData> getPictures() {
- return pictures;
+ return Collections.unmodifiableList(pictures);
}
/**
@@ -147,7 +148,7 @@ public abstract class XWPFAbstractFootnoteEndnote implements Iterable<XWPFParag
*/
@Override
public List<IBodyElement> getBodyElements() {
- return bodyElements;
+ return Collections.unmodifiableList(bodyElements);
}
/**
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFAbstractSDT.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFAbstractSDT.java
index 434d857f2c..78ed571886 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFAbstractSDT.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFAbstractSDT.java
@@ -30,12 +30,13 @@ public abstract class XWPFAbstractSDT implements ISDTContents {
private final String title;
private final String tag;
private final IBody part;
+ private final XWPFDocument xwpfDocument;
public XWPFAbstractSDT(CTSdtPr pr, IBody part) {
title = (pr != null && pr.isSetAlias()) ? pr.getAlias().getVal() : "";
tag = (pr != null && pr.isSetTag()) ? pr.getTag().getVal() : "";
this.part = part;
-
+ this.xwpfDocument = part.getXWPFDocument();
}
/**
@@ -86,6 +87,6 @@ public abstract class XWPFAbstractSDT implements ISDTContents {
}
public XWPFDocument getDocument() {
- return part.getXWPFDocument();
+ return xwpfDocument;
}
}
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFComments.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFComments.java
index 1aff90af29..5cbba917eb 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFComments.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFComments.java
@@ -25,6 +25,7 @@ import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal;
+import org.apache.poi.util.Removal;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTComment;
@@ -141,7 +142,10 @@ public class XWPFComments extends POIXMLDocumentPart {
* @return the index to this picture (0 based), the added picture can be
* obtained from {@link #getAllPictures()} .
* @throws InvalidFormatException If the format of the picture is not known.
+ * @deprecated use {@link #addPictureData(byte[], PictureType)} instead.
*/
+ @Deprecated
+ @Removal(version = "7.0.0")
public String addPictureData(byte[] pictureData, int format) throws InvalidFormatException {
return addPictureData(pictureData, PictureType.findByOoxmlId(format));
}
@@ -233,7 +237,7 @@ public class XWPFComments extends POIXMLDocumentPart {
* Get the list of {@link XWPFComment} in the Comments part.
*/
public List<XWPFComment> getComments() {
- return comments;
+ return Collections.unmodifiableList(comments);
}
/**
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java
index 88a603e160..eb8c4c30c9 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java
@@ -60,6 +60,7 @@ import org.apache.poi.openxml4j.opc.TargetMode;
import org.apache.poi.poifs.crypt.HashAlgorithm;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal;
+import org.apache.poi.util.Removal;
import org.apache.poi.wp.usermodel.HeaderFooterType;
import org.apache.poi.xddf.usermodel.chart.XDDFChart;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
@@ -1724,7 +1725,10 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody {
* @return the next free ImageNumber
* @throws InvalidFormatException If the format of the picture is not known.
* @see #getNextPicNameNumber(PictureType)
+ * @deprecated use {@link #getNextPicNameNumber(PictureType)} instead.
*/
+ @Deprecated
+ @Removal(version = "7.0.0")
public int getNextPicNameNumber(int format) throws InvalidFormatException {
return getNextPicNameNumber(PictureType.findByOoxmlId(format));
}
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFHeaderFooter.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFHeaderFooter.java
index 225a8f496e..3c80d26a0a 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFHeaderFooter.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFHeaderFooter.java
@@ -31,6 +31,7 @@ import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal;
+import org.apache.poi.util.Removal;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHdrFtr;
@@ -210,7 +211,7 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo
* @return a list of {@link XWPFParagraph}
*/
public List<XWPFParagraph> getListParagraph() {
- return paragraphs;
+ return Collections.unmodifiableList(paragraphs);
}
public List<XWPFPictureData> getAllPictures() {
@@ -235,7 +236,10 @@ public abstract class XWPFHeaderFooter extends POIXMLDocumentPart implements IBo
* @return the index to this picture (0 based), the added picture can be obtained from {@link #getAllPictures()} .
* @throws InvalidFormatException If the format of the picture is not known.
* @see #addPictureData(byte[], PictureType)
+ * @deprecated Use {@link #addPictureData(byte[], PictureType)} instead.
*/
+ @Deprecated
+ @Removal(version = "7.0.0")
public String addPictureData(byte[] pictureData, int format) throws InvalidFormatException {
return addPictureData(pictureData, PictureType.findByOoxmlId(format));
}
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFPictureData.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFPictureData.java
index 7d541a627f..7749977f01 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFPictureData.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFPictureData.java
@@ -28,6 +28,7 @@ import org.apache.poi.ooxml.POIXMLRelation;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.Removal;
/**
* Raw picture data, normally attached to a WordprocessingML Drawing.
@@ -152,8 +153,10 @@ public class XWPFPictureData extends POIXMLDocumentPart {
* @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_GIF
* @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_DIB
* @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_SVG
- * @see #getPictureTypeEnum()
+ * @deprecated use #getPictureTypeEnum()
*/
+ @Deprecated
+ @Removal(version = "7.0.0") // repurpose to return PictureType
public int getPictureType() {
String contentType = getPackagePart().getContentType();
for (int i = 0; i < RELATIONS.length; i++) {
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFRun.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFRun.java
index 29339e1453..645373e042 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFRun.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFRun.java
@@ -26,11 +26,13 @@ import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import javax.xml.namespace.QName;
import org.apache.poi.common.usermodel.PictureType;
+import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.ooxml.POIXMLException;
import org.apache.poi.ooxml.util.DocumentHelper;
import org.apache.poi.ooxml.util.POIXMLUnits;
@@ -41,6 +43,7 @@ import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.apache.xmlbeans.*;
import org.apache.xmlbeans.impl.values.XmlAnyTypeImpl;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTChart;
+import org.openxmlformats.schemas.drawingml.x2006.chart.CTRelId;
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlip;
import org.openxmlformats.schemas.drawingml.x2006.main.CTBlipFillProperties;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObject;
@@ -75,6 +78,7 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun {
private final String pictureText;
private final IRunBody parent;
private final List<XWPFPicture> pictures;
+ private final List<XWPFChart> charts;
/**
* @param r the CTR bean which holds the run attributes
@@ -122,14 +126,25 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun {
}
pictureText = text.toString();
- // Do we have any embedded pictures?
- // (They're a different CTPicture, under the drawingml namespace)
+ // Do we have any embedded pictures or charts?
+ // Pictures are a different CTPicture, under the drawingml namespace.
+ // Charts are relations and use the CTRelId type.
pictures = new ArrayList<>();
+ charts = new ArrayList<>();
for (XmlObject o : pictTextObjs) {
for (CTPicture pict : getCTPictures(o)) {
XWPFPicture picture = new XWPFPicture(pict, this);
pictures.add(picture);
}
+ XmlObject[] chartRels = o.selectPath("declare namespace c='" + CTChart.type.getName().getNamespaceURI() + "' .//*/c:chart");
+ for (XmlObject chartRel : chartRels) {
+ if (chartRel instanceof CTRelId) {
+ POIXMLDocumentPart chart = getDocument().getRelationById(((CTRelId) chartRel).getId());
+ if (chart instanceof XWPFChart) {
+ charts.add((XWPFChart) chart);
+ }
+ }
+ }
}
}
@@ -1223,8 +1238,10 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun {
* @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_GIF
* @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_DIB
* @see org.apache.poi.xwpf.usermodel.Document#PICTURE_TYPE_SVG
- * @see #addPicture(InputStream, PictureType, String, int, int)
+ * @deprecated use #addPicture(InputStream, PictureType, String, int, int)
*/
+ @Deprecated
+ @Removal(version = "7.0.0")
public XWPFPicture addPicture(InputStream pictureData, int pictureType, String filename, int width, int height)
throws InvalidFormatException, IOException {
return addPicture(pictureData, PictureType.findByOoxmlId(pictureType), filename, width, height);
@@ -1358,6 +1375,11 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun {
@Internal
public CTInline addChart(String chartRelId) throws InvalidFormatException, IOException {
try {
+ POIXMLDocumentPart chart = getDocument().getRelationById(chartRelId);
+ if (chart instanceof XWPFChart) {
+ charts.add((XWPFChart) chart);
+ }
+
CTInline inline = run.addNewDrawing().addNewInline();
//xml part of chart in document
@@ -1399,7 +1421,7 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun {
* embedded picture image such as a .png or .jpg
*/
public List<XWPFPicture> getEmbeddedPictures() {
- return pictures;
+ return Collections.unmodifiableList(pictures);
}
/**
@@ -1817,4 +1839,12 @@ public class XWPFRun implements ISDTContents, IRunElement, CharacterRun {
return pr;
}
+ /**
+ * Returns the charts embedded in the run.
+ * @return A list of the XWPFChart objects embedded in the run.
+ * @since POI 5.5.0
+ */
+ public List<XWPFChart> getEmbeddedCharts() {
+ return Collections.unmodifiableList(charts);
+ }
}
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFSDTCell.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFSDTCell.java
index 5589287263..132fa95e11 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFSDTCell.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFSDTCell.java
@@ -29,9 +29,11 @@ import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSdtCell;
*/
public class XWPFSDTCell extends XWPFAbstractSDT implements ICell {
private final XWPFSDTContentCell cellContent;
+ private final CTSdtCell sdtCell;
public XWPFSDTCell(CTSdtCell sdtCell, XWPFTableRow xwpfTableRow, IBody part) {
super(sdtCell.getSdtPr(), part);
+ this.sdtCell = sdtCell;
cellContent = new XWPFSDTContentCell(sdtCell.getSdtContent(), xwpfTableRow, part);
}
@@ -40,4 +42,12 @@ public class XWPFSDTCell extends XWPFAbstractSDT implements ICell {
return cellContent;
}
+ /**
+ * Return the underlying XML bean.
+ * @return the underlying CTSdtCell bean.
+ * @since POI 5.5.0
+ */
+ public CTSdtCell getCTSdtCell() {
+ return sdtCell;
+ }
}
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFSDTContentCell.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFSDTContentCell.java
index d43e24fc43..3da8b87b9a 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFSDTContentCell.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFSDTContentCell.java
@@ -40,14 +40,19 @@ public class XWPFSDTContentCell implements ISDTContent {
//private List<ICell> cells = new ArrayList<ICell>().
- private String text = "";
+ private final CTSdtContentCell sdtContentCell;
+ private String text;
public XWPFSDTContentCell(CTSdtContentCell sdtContentCell,
XWPFTableRow xwpfTableRow, IBody part) {
super();
+ this.sdtContentCell = sdtContentCell;
+ }
+
+ private String extractTextFromSdtContentCell() {
//sdtContentCell is allowed to be null: minOccurs="0" maxOccurs="1"
if (sdtContentCell == null) {
- return;
+ return "";
}
StringBuilder sb = new StringBuilder();
try (final XmlCursor cursor = sdtContentCell.newCursor()) {
@@ -87,7 +92,7 @@ public class XWPFSDTContentCell implements ISDTContent {
depth--;
}
}
- text = sb.toString();
+ return sb.toString();
}
}
@@ -103,12 +108,25 @@ public class XWPFSDTContentCell implements ISDTContent {
return false;
}
-
+ @Override
public String getText() {
+ if (text == null) {
+ text = extractTextFromSdtContentCell();
+ }
return text;
}
+ @Override
public String toString() {
return getText();
}
+
+ /**
+ * Return the underlying XML bean.
+ * @return the underlying CTSdtContentCell bean.
+ * @since POI 5.5.0
+ */
+ public CTSdtContentCell getCTSdtContentCell() {
+ return sdtContentCell;
+ }
}
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTableCell.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTableCell.java
index f91d9a1d81..27f7dbfaf9 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTableCell.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTableCell.java
@@ -67,6 +67,7 @@ public class XWPFTableCell implements IBody, ICell {
}
private final CTTc ctTc;
+ private final XWPFDocument xwpfDocument;
protected List<XWPFParagraph> paragraphs;
protected List<XWPFTable> tables;
protected List<IBodyElement> bodyElements;
@@ -81,6 +82,7 @@ public class XWPFTableCell implements IBody, ICell {
this.ctTc = cell;
this.part = part;
this.tableRow = tableRow;
+ this.xwpfDocument = part.getXWPFDocument();
bodyElements = new ArrayList<>();
paragraphs = new ArrayList<>();
@@ -524,7 +526,26 @@ public class XWPFTableCell implements IBody, ICell {
@Override
public XWPFDocument getXWPFDocument() {
- return part.getXWPFDocument();
+ if (xwpfDocument != null) {
+ return xwpfDocument;
+ } else if (part instanceof XWPFTableCell) {
+ return getCellDocument((XWPFTableCell) part, 0);
+ } else {
+ return part.getXWPFDocument();
+ }
+ }
+
+ private static final int MAX_RECURSION_DEPTH = 1000;
+
+ private static XWPFDocument getCellDocument(XWPFTableCell cell, final int depth) {
+ if (depth > MAX_RECURSION_DEPTH) {
+ throw new IllegalStateException("Recursion depth exceeded while trying to get XWPFDocument from XWPFTableCell");
+ }
+ if (cell.part instanceof XWPFTableCell) {
+ return getCellDocument((XWPFTableCell) cell.part, depth + 1);
+ } else {
+ return cell.part.getXWPFDocument();
+ }
}
// Create a map from this XWPF-level enum to the STVerticalJc.Enum values
diff --git a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTableRow.java b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTableRow.java
index f27df6dc24..4b43c0817c 100644
--- a/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTableRow.java
+++ b/poi-ooxml/src/main/java/org/apache/poi/xwpf/usermodel/XWPFTableRow.java
@@ -18,6 +18,7 @@ package org.apache.poi.xwpf.usermodel;
import java.math.BigInteger;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import org.apache.poi.ooxml.util.POIXMLUnits;
@@ -211,7 +212,7 @@ public class XWPFTableRow {
this.tableCells = cells;
}
- return tableCells;
+ return Collections.unmodifiableList(tableCells);
}
/**
diff --git a/poi-ooxml/src/test/java/org/apache/poi/xddf/usermodel/chart/TestXDDFChartRemoveSeries.java b/poi-ooxml/src/test/java/org/apache/poi/xddf/usermodel/chart/TestXDDFChartRemoveSeries.java
index 8bea979e33..5ebd7d13b5 100644
--- a/poi-ooxml/src/test/java/org/apache/poi/xddf/usermodel/chart/TestXDDFChartRemoveSeries.java
+++ b/poi-ooxml/src/test/java/org/apache/poi/xddf/usermodel/chart/TestXDDFChartRemoveSeries.java
@@ -112,21 +112,7 @@ class TestXDDFChartRemoveSeries {
}
workbook.close();
}
-
- /**
- * Attempt to remove the first series by calling chartData.getSeries().remove(0).
- * <p>
- * This used to corrupt the workbook but the returned <code>List</code> is unmodifiable.
- */
- @Test
- void testRemoveSeries0() {
- procName = "testRemoveSeries0";
- fileName = procName + ".xlsx";
-
- assertThrows(UnsupportedOperationException.class, () -> chartData.getSeries().remove(0));
- assertEquals(2, chartData.getSeriesCount());
- }
-
+
/**
* Remove the first series by calling chartData.removeSeries(0).
* <p>
diff --git a/poi-ooxml/src/test/java/org/apache/poi/xssf/model/TestExternalLinksTable.java b/poi-ooxml/src/test/java/org/apache/poi/xssf/model/TestExternalLinksTable.java
index 045a03601b..9677cb0a7f 100644
--- a/poi-ooxml/src/test/java/org/apache/poi/xssf/model/TestExternalLinksTable.java
+++ b/poi-ooxml/src/test/java/org/apache/poi/xssf/model/TestExternalLinksTable.java
@@ -32,18 +32,18 @@ public final class TestExternalLinksTable {
@Test
void none() throws IOException {
try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("SampleSS.xlsx")) {
- assertNotNull(wb.getExternalLinksTable());
- assertEquals(0, wb.getExternalLinksTable().size());
+ assertNotNull(wb.getExternalLinksTables());
+ assertEquals(0, wb.getExternalLinksTables().size());
}
}
@Test
void basicRead() throws IOException {
try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("ref-56737.xlsx")) {
- assertNotNull(wb.getExternalLinksTable());
- assertEquals(1, wb.getExternalLinksTable().size());
+ assertNotNull(wb.getExternalLinksTables());
+ assertEquals(1, wb.getExternalLinksTables().size());
- ExternalLinksTable links = wb.getExternalLinksTable().get(0);
+ ExternalLinksTable links = wb.getExternalLinksTable(0);
assertEquals(3, links.getSheetNames().size());
assertEquals(2, links.getDefinedNames().size());
@@ -70,13 +70,13 @@ public final class TestExternalLinksTable {
@Test
void basicReadWriteRead() throws IOException {
try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("ref-56737.xlsx")) {
- Name name = wb.getExternalLinksTable().get(0).getDefinedNames().get(1);
+ Name name = wb.getExternalLinksTable(0).getDefinedNames().get(1);
name.setNameName("Testing");
name.setRefersToFormula("$A$1");
XSSFWorkbook wbBack = XSSFTestDataSamples.writeOutAndReadBack(wb);
- assertEquals(1, wbBack.getExternalLinksTable().size());
- ExternalLinksTable links = wbBack.getExternalLinksTable().get(0);
+ assertEquals(1, wbBack.getExternalLinksTables().size());
+ ExternalLinksTable links = wbBack.getExternalLinksTable(0);
name = links.getDefinedNames().get(0);
assertEquals("NR_Global_B2", name.getNameName());
@@ -95,11 +95,11 @@ public final class TestExternalLinksTable {
@Test
void readWithReferencesToTwoExternalBooks() throws IOException {
try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("ref2-56737.xlsx")) {
- assertNotNull(wb.getExternalLinksTable());
- assertEquals(2, wb.getExternalLinksTable().size());
+ assertNotNull(wb.getExternalLinksTables());
+ assertEquals(2, wb.getExternalLinksTables().size());
// Check the first one, links to 56737.xlsx
- ExternalLinksTable links = wb.getExternalLinksTable().get(0);
+ ExternalLinksTable links = wb.getExternalLinksTable(0);
assertEquals("56737.xlsx", links.getLinkedFileName());
assertEquals(3, links.getSheetNames().size());
assertEquals(2, links.getDefinedNames().size());
@@ -122,7 +122,7 @@ public final class TestExternalLinksTable {
// Check the second one, links to 56737.xls, slightly differently
- links = wb.getExternalLinksTable().get(1);
+ links = wb.getExternalLinksTable(1);
assertEquals("56737.xls", links.getLinkedFileName());
assertEquals(2, links.getSheetNames().size());
assertEquals(2, links.getDefinedNames().size());
diff --git a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFPictureData.java b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFPictureData.java
index b42aeba053..fa1cb56136 100644
--- a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFPictureData.java
+++ b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFPictureData.java
@@ -35,7 +35,7 @@ public final class TestXSSFPictureData {
XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("WithDrawing.xlsx");
List<XSSFPictureData> pictures = wb.getAllPictures();
//wb.getAllPictures() should return the same instance across multiple calls
- assertSame(pictures, wb.getAllPictures());
+ assertEquals(pictures, wb.getAllPictures());
assertEquals(5, pictures.size());
String[] ext = {"jpeg", "emf", "png", "emf", "wmf"};
diff --git a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java
index 7926912f6c..19da165b85 100644
--- a/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java
+++ b/poi-ooxml/src/test/java/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java
@@ -1391,7 +1391,7 @@ public final class TestXSSFWorkbook extends BaseTestXWorkbook {
try(
XSSFWorkbook workbook2 = new XSSFWorkbook(bosB.toInputStream())
) {
- CTExternalLink link = workbook2.getExternalLinksTable().get(0).getCTExternalLink();
+ CTExternalLink link = workbook2.getExternalLinksTable(0).getCTExternalLink();
CTExternalSheetData sheetData = link.getExternalBook().getSheetDataSet().getSheetDataArray(0);
assertEquals(Double.valueOf(sheetData.getRowArray(0).getCellArray(0).getV()), v1);
assertEquals(Double.valueOf(sheetData.getRowArray(0).getCellArray(1).getV()), v2);
diff --git a/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFComment.java b/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFComment.java
index 79ffa2d701..256fe9fe7e 100644
--- a/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFComment.java
+++ b/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFComment.java
@@ -16,6 +16,7 @@
==================================================================== */
package org.apache.poi.xwpf.usermodel;
+import org.apache.poi.common.usermodel.PictureType;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.xwpf.XWPFTestDataSamples;
@@ -100,7 +101,7 @@ class TestXWPFComment {
XWPFParagraph paragraph = comment.createParagraph();
XWPFRun r = paragraph.createRun();
r.addPicture(new ByteArrayInputStream(new byte[0]),
- Document.PICTURE_TYPE_JPEG, "test.jpg", 21, 32);
+ PictureType.JPEG, "test.jpg", 21, 32);
assertEquals(1, comments.getAllPictures().size());
assertEquals(1, doc.getAllPackagePictures().size());
diff --git a/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFPictureData.java b/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFPictureData.java
index 926ea82868..452c869995 100644
--- a/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFPictureData.java
+++ b/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFPictureData.java
@@ -117,7 +117,7 @@ class TestXWPFPictureData {
// Add a picture to the first paragraph
header.getParagraphs().get(0).getRuns().get(0).addPicture(
new ByteArrayInputStream(new byte[]{1, 2, 3, 4}),
- Document.PICTURE_TYPE_JPEG, "test.jpg", 2, 2);
+ PictureType.JPEG, "test.jpg", 2, 2);
// Check
verifyOneHeaderPicture(doc);
diff --git a/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFRun.java b/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFRun.java
index ed79c2272d..87561e720d 100644
--- a/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFRun.java
+++ b/poi-ooxml/src/test/java/org/apache/poi/xwpf/usermodel/TestXWPFRun.java
@@ -36,6 +36,7 @@ import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.Units;
import org.apache.poi.wp.usermodel.HeaderFooterType;
+import org.apache.poi.xddf.usermodel.chart.XDDFChart;
import org.apache.poi.xwpf.XWPFTestDataSamples;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.junit.jupiter.api.AfterEach;
@@ -552,7 +553,7 @@ class TestXWPFRun {
assertEquals(0, doc.getAllPictures().size());
assertEquals(0, r.getEmbeddedPictures().size());
- r.addPicture(new ByteArrayInputStream(new byte[0]), Document.PICTURE_TYPE_JPEG, "test.jpg", 21, 32);
+ r.addPicture(new ByteArrayInputStream(new byte[0]), PictureType.JPEG, "test.jpg", 21, 32);
assertEquals(1, doc.getAllPictures().size());
assertEquals(1, r.getEmbeddedPictures().size());
@@ -580,7 +581,7 @@ class TestXWPFRun {
assertEquals(0, hdr.getAllPictures().size());
assertEquals(0, r.getEmbeddedPictures().size());
- r.addPicture(new ByteArrayInputStream(new byte[0]), Document.PICTURE_TYPE_JPEG, "test.jpg", 21, 32);
+ r.addPicture(new ByteArrayInputStream(new byte[0]), PictureType.JPEG, "test.jpg", 21, 32);
assertEquals(1, hdr.getAllPictures().size());
assertEquals(1, r.getEmbeddedPictures().size());
@@ -627,7 +628,7 @@ class TestXWPFRun {
try (XWPFDocument document = new XWPFDocument()) {
document.createParagraph().createRun().addPicture(
- new ByteArrayInputStream(image), Document.PICTURE_TYPE_JPEG, "test.jpg", Units.toEMU(300), Units.toEMU(100));
+ new ByteArrayInputStream(image), PictureType.JPEG, "test.jpg", Units.toEMU(300), Units.toEMU(100));
try (XWPFDocument docBack = writeOutAndReadBack(document)) {
List<XWPFPicture> pictures = docBack.getParagraphArray(0).getRuns().get(0).getEmbeddedPictures();
@@ -858,7 +859,7 @@ class TestXWPFRun {
assertEquals(0, hdr.getAllPictures().size());
assertEquals(0, r.getEmbeddedPictures().size());
- r.addPicture(new ByteArrayInputStream(new byte[0]), Document.PICTURE_TYPE_JPEG, "test.jpg", 21, 32);
+ r.addPicture(new ByteArrayInputStream(new byte[0]), PictureType.JPEG, "test.jpg", 21, 32);
assertEquals(1, hdr.getAllPictures().size());
assertEquals(1, r.getEmbeddedPictures().size());
@@ -909,4 +910,34 @@ class TestXWPFRun {
run.setText("TEST STRING");
assertEquals(1, run.getNumberOfTexts());
}
+
+ @Test
+ void testGetEmbeddedCharts() throws IOException {
+ try (XWPFDocument sampleDoc = XWPFTestDataSamples.openSampleDocument("61745.docx")) {
+ List<XWPFChart> charts = sampleDoc.getCharts();
+ assertEquals(2, charts.size());
+ List<XWPFChart> run1Charts = sampleDoc.getParagraphArray(0).getRuns().get(0).getEmbeddedCharts();
+ assertEquals(1, run1Charts.size());
+ assertEquals(charts.get(0), run1Charts.get(0));
+ List<XWPFChart> run2Charts = sampleDoc.getParagraphArray(1).getRuns().get(0).getEmbeddedCharts();
+ assertEquals(1, run2Charts.size());
+ assertEquals(charts.get(1), run2Charts.get(0));
+ }
+ }
+
+ @Test
+ void testAddChartGetEmbeddedCharts() throws InvalidFormatException, IOException {
+ XWPFRun run1 = p.createRun();
+ XWPFChart chart1 = doc.createChart(run1, XDDFChart.DEFAULT_WIDTH, XDDFChart.DEFAULT_HEIGHT);
+ assertEquals(1, run1.getEmbeddedCharts().size());
+ assertEquals(chart1, run1.getEmbeddedCharts().get(0));
+
+ XWPFRun run2 = p.createRun();
+ XWPFChart chart2 = doc.createChart(run2, XDDFChart.DEFAULT_WIDTH, XDDFChart.DEFAULT_HEIGHT);
+ assertEquals(1, run2.getEmbeddedCharts().size());
+ assertEquals(chart2, run2.getEmbeddedCharts().get(0));
+
+ XWPFRun run3 = p.createRun();
+ assertEquals(0, run3.getEmbeddedCharts().size());
+ }
}
diff --git a/poi/src/main/java/org/apache/poi/hssf/util/HSSFColor.java b/poi/src/main/java/org/apache/poi/hssf/util/HSSFColor.java
index 107b116798..cc3d3ed796 100644
--- a/poi/src/main/java/org/apache/poi/hssf/util/HSSFColor.java
+++ b/poi/src/main/java/org/apache/poi/hssf/util/HSSFColor.java
@@ -182,7 +182,7 @@ public class HSSFColor implements Color {
* @param index
* @param index2
* @param rgb combined value of RGB
- * @since POI 5.4.2
+ * @since POI 5.5.0
*/
public HSSFColor(int index, int index2, int rgb) {
this.index = index;
diff --git a/poi/src/main/java/org/apache/poi/poifs/dev/POIFSDump.java b/poi/src/main/java/org/apache/poi/poifs/dev/POIFSDump.java
index d29745ea82..fdf6bb85f4 100644
--- a/poi/src/main/java/org/apache/poi/poifs/dev/POIFSDump.java
+++ b/poi/src/main/java/org/apache/poi/poifs/dev/POIFSDump.java
@@ -71,7 +71,7 @@ public final class POIFSDump {
DirectoryEntry root = fs.getRoot();
String filenameWithoutPath = new File(filename).getName();
File dumpDir = new File(filenameWithoutPath + "_dump");
- File file = new File(dumpDir, root.getName());
+ File file = IOUtils.newFile(dumpDir, root.getName());
if (!file.exists() && !file.mkdirs()) {
throw new IOException("Could not create directory " + file);
}
@@ -104,13 +104,14 @@ public final class POIFSDump {
try (DocumentInputStream is = new DocumentInputStream(node)) {
bytes = IOUtils.toByteArray(is);
}
- try (OutputStream out = Files.newOutputStream(new File(parent, node.getName().trim()).toPath())) {
+ try (OutputStream out = Files.newOutputStream(
+ IOUtils.newFile(parent, node.getName().trim()).toPath())) {
out.write(bytes);
}
} else if (entry instanceof DirectoryEntry){
DirectoryEntry dir = (DirectoryEntry)entry;
- File file = new File(parent, entry.getName());
- if(!file.exists() && !file.mkdirs()) {
+ File file = IOUtils.newFile(parent, entry.getName());
+ if (!file.exists() && !file.mkdirs()) {
throw new IOException("Could not create directory " + file);
}
dump(dir, file);
@@ -119,8 +120,9 @@ public final class POIFSDump {
}
}
}
+
public static void dump(POIFSFileSystem fs, int startBlock, String name, File parent) throws IOException {
- File file = new File(parent, name);
+ File file = IOUtils.newFile(parent, name);
try (OutputStream out = Files.newOutputStream(file.toPath())) {
POIFSStream stream = new POIFSStream(fs, startBlock);
diff --git a/poi/src/main/java/org/apache/poi/poifs/macros/VBAMacroExtractor.java b/poi/src/main/java/org/apache/poi/poifs/macros/VBAMacroExtractor.java
index c0db47e5fb..e5a80e9034 100644
--- a/poi/src/main/java/org/apache/poi/poifs/macros/VBAMacroExtractor.java
+++ b/poi/src/main/java/org/apache/poi/poifs/macros/VBAMacroExtractor.java
@@ -26,6 +26,7 @@ import java.nio.file.Files;
import java.util.Map;
import java.util.Map.Entry;
+import org.apache.poi.util.IOUtils;
import org.apache.poi.util.StringUtil;
/**
@@ -95,7 +96,7 @@ public class VBAMacroExtractor {
System.out.println();
System.out.println(moduleCode);
} else {
- File out = new File(outputDir, moduleName + extension);
+ File out = IOUtils.newFile(outputDir, moduleName + extension);
try (OutputStream fout = Files.newOutputStream(out.toPath());
OutputStreamWriter fwriter = new OutputStreamWriter(fout, StringUtil.UTF8)) {
fwriter.write(moduleCode);
diff --git a/poi/src/main/java/org/apache/poi/poifs/property/PropertyTable.java b/poi/src/main/java/org/apache/poi/poifs/property/PropertyTable.java
index 062627ae52..562413e0c6 100644
--- a/poi/src/main/java/org/apache/poi/poifs/property/PropertyTable.java
+++ b/poi/src/main/java/org/apache/poi/poifs/property/PropertyTable.java
@@ -111,7 +111,7 @@ public final class PropertyTable implements BATManaged {
Property property = _properties.get(0);
if (property != null) {
if (property instanceof DirectoryProperty) {
- populatePropertyTree((DirectoryProperty) property);
+ populatePropertyTree((DirectoryProperty) property, 0);
} else {
throw new IOException("Invalid format, cannot convert property " + property + " to DirectoryProperty");
}
@@ -227,7 +227,14 @@ public final class PropertyTable implements BATManaged {
_header_block.setPropertyCount(countBlocks());
}
- private void populatePropertyTree(DirectoryProperty root) throws IOException {
+ // Maximum depth of the property tree to prevent stackoverflow errors
+ private static final int MAX_PROPERTY_DEPTH = 1000;
+
+ private void populatePropertyTree(final DirectoryProperty root, final int depth) throws IOException {
+ if (depth > MAX_PROPERTY_DEPTH) {
+ throw new IOException("Property tree too deep, likely a corrupt file");
+ }
+
int index = root.getChildIndex();
if (!Property.isValidIndex(index)) {
@@ -246,7 +253,7 @@ public final class PropertyTable implements BATManaged {
root.addChild(property);
if (property.isDirectory()) {
- populatePropertyTree(( DirectoryProperty ) property);
+ populatePropertyTree((DirectoryProperty) property, depth + 1);
}
index = property.getPreviousChildIndex();
if (isValidIndex(index)) {
diff --git a/poi/src/main/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java b/poi/src/main/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java
index d7e2db2236..a34b8b370d 100644
--- a/poi/src/main/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java
+++ b/poi/src/main/java/org/apache/poi/ss/formula/atp/AnalysisToolPak.java
@@ -288,7 +288,7 @@ public final class AnalysisToolPak implements UDFFinder {
* @param func the function to register
* @param force force registration even if the function is already registered or unknown to POI
* @throws IllegalArgumentException if the function is unknown or already registered (and `force` is not true).
- * @since POI 5.4.2
+ * @since POI 5.5.0
*/
public static void registerFunction(String name, FreeRefFunction func, boolean force) {
AnalysisToolPak inst = (AnalysisToolPak)instance;
diff --git a/poi/src/main/java/org/apache/poi/ss/usermodel/DateUtil.java b/poi/src/main/java/org/apache/poi/ss/usermodel/DateUtil.java
index 401b1c47a1..452c8948bb 100644
--- a/poi/src/main/java/org/apache/poi/ss/usermodel/DateUtil.java
+++ b/poi/src/main/java/org/apache/poi/ss/usermodel/DateUtil.java
@@ -1008,7 +1008,7 @@ public class DateUtil {
* If disabled, the cache will not be used and each check will be performed independently.
*
* @param enable true to enable the cache, false to disable it (enabled, by default)
- * @since POI 5.4.2
+ * @since POI 5.5.0
*/
public static void enableThreadLocalCache(final boolean enable) {
// enable thread-local cache for date format checking
diff --git a/poi/src/main/java/org/apache/poi/ss/util/CellUtil.java b/poi/src/main/java/org/apache/poi/ss/util/CellUtil.java
index b2879fb7fd..7c1b3ad81e 100644
--- a/poi/src/main/java/org/apache/poi/ss/util/CellUtil.java
+++ b/poi/src/main/java/org/apache/poi/ss/util/CellUtil.java
@@ -880,7 +880,7 @@ public final class CellUtil {
* @param dest destination cell style
* @param destWorkbook destination workbook (can be null but some font info will not be copied if null is passed)
* @throws IllegalArgumentException if source or destination styles are null
- * @since POI 5.4.2
+ * @since POI 5.5.0
*/
@Internal
public static void cloneStyle(CellStyle src, CellStyle dest, Workbook destWorkbook) {
diff --git a/poi/src/main/java/org/apache/poi/util/DefaultTempFileCreationStrategy.java b/poi/src/main/java/org/apache/poi/util/DefaultTempFileCreationStrategy.java
index 584f7dec4c..48495c94a3 100644
--- a/poi/src/main/java/org/apache/poi/util/DefaultTempFileCreationStrategy.java
+++ b/poi/src/main/java/org/apache/poi/util/DefaultTempFileCreationStrategy.java
@@ -71,7 +71,7 @@ public class DefaultTempFileCreationStrategy implements TempFileCreationStrategy
* Creates the strategy allowing to set a custom directory for the temporary files.
* <p>
* If you provide a non-null dir as input, it must be a directory (if it already exists).
- * Since POI 5.4.2, this is checked at construction time. In previous versions, it was checked
+ * Since POI 5.5.0, this is checked at construction time. In previous versions, it was checked
* at the first call to {@link #createTempFile(String, String)} or {@link #createTempDirectory(String)}.
* </p>
*
diff --git a/poi/src/main/java/org/apache/poi/util/IOUtils.java b/poi/src/main/java/org/apache/poi/util/IOUtils.java
index ff86043a54..3487c00f96 100644
--- a/poi/src/main/java/org/apache/poi/util/IOUtils.java
+++ b/poi/src/main/java/org/apache/poi/util/IOUtils.java
@@ -601,7 +601,6 @@ public final class IOUtils {
return Arrays.copyOfRange(src, offset, offset+realLength);
}
-
/**
* Simple utility function to check that you haven't hit EOF
* when reading a byte.
@@ -618,6 +617,28 @@ public final class IOUtils {
return b;
}
+ /**
+ * Creates a new file in the given parent directory with the given name.
+ * There is a check to prevent path traversal attacks. Only path traversal
+ * that would lead to a file outside the parent directory is regarded as an issue.
+ *
+ * @param parent The parent directory where the file should be created.
+ * @param name The name of the file to create.
+ * @return The created file.
+ * @throws IOException If path traversal is detected.
+ * @since POI 5.5.0
+ */
+ public static File newFile(final File parent, final String name) throws IOException {
+ final File file = new File(parent, name);
+ if (!file.toPath().toAbsolutePath().normalize().startsWith(
+ parent.toPath().toAbsolutePath().normalize()
+ )) {
+ throw new IOException(String.format(
+ Locale.ROOT, "Failing due to path traversal in `%s`", name));
+ }
+ return file;
+ }
+
private static void throwRFE(long length, int maxLength) {
throw new RecordFormatException(String.format(Locale.ROOT, "Tried to allocate an array of length %,d" +
", but the maximum length for this record type is %,d.%n" +
diff --git a/poi/src/main/java/org/apache/poi/util/TempFile.java b/poi/src/main/java/org/apache/poi/util/TempFile.java
index 2b668dc885..f5ab4e6f4a 100644
--- a/poi/src/main/java/org/apache/poi/util/TempFile.java
+++ b/poi/src/main/java/org/apache/poi/util/TempFile.java
@@ -62,7 +62,7 @@ public final class TempFile {
*
* @param strategy The new strategy to be used to create the temporary files for this thread.
* <code>null</code> can be used to reset the strategy for this thread to the default one.
- * @since POI 5.4.2
+ * @since POI 5.5.0
*/
public static void setThreadLocalTempFileCreationStrategy(TempFileCreationStrategy strategy) {
if (strategy == null) {
@@ -104,7 +104,7 @@ public final class TempFile {
* @param task the task to be executed with the given temp file strategy
* @return the result of the given task
*
- * @since POI 5.4.2
+ * @since POI 5.5.0
*/
public static <R> R withStrategy(TempFileCreationStrategy newStrategy, Supplier<? extends R> task) {
Objects.requireNonNull(newStrategy, "newStrategy");
diff --git a/poi/src/test/java/org/apache/poi/util/TestIOUtils.java b/poi/src/test/java/org/apache/poi/util/TestIOUtils.java
index 7f026adc74..094e138eef 100644
--- a/poi/src/test/java/org/apache/poi/util/TestIOUtils.java
+++ b/poi/src/test/java/org/apache/poi/util/TestIOUtils.java
@@ -41,6 +41,7 @@ import java.nio.charset.StandardCharsets;
import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
import org.apache.poi.EmptyFileException;
import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.Isolated;
@@ -575,6 +576,59 @@ final class TestIOUtils {
assertEquals(4, ret.length);
}
+ @Test
+ void testNewFile() throws IOException {
+ final File parent = TempFile.createTempDirectory("create-file-test");
+ try {
+ final String path0 = "path/to/file.txt";
+ final File outFile = IOUtils.newFile(parent, path0);
+ assertTrue(outFile.getAbsolutePath().endsWith(path0),
+ "unexpected path: " + outFile.getAbsolutePath());
+ } finally {
+ assertTrue(parent.delete());
+ }
+ }
+
+ @Test
+ void testAllowedPathTraversal() throws IOException {
+ final File parent = TempFile.createTempDirectory("path-traversal-test");
+ try {
+ // this path is ok because it doesn't walk out of the parent directory
+ final String path0 = "a/b/c/../d/e/../../f/g/./h";
+ File outFile = IOUtils.newFile(parent, path0);
+ assertTrue(outFile.getAbsolutePath().endsWith(path0),
+ "unexpected path: " + outFile.getAbsolutePath());
+ } finally {
+ assertTrue(parent.delete());
+ }
+ }
+
+ @Test
+ void testAllowedPathTraversal2() throws IOException {
+ final File parent = TempFile.createTempDirectory("path-traversal-test");
+ try {
+ // this path is ok because it doesn't walk out of the parent directory
+ // the initial slash is ignored and the generated path is relative to the parent directory
+ final String path0 = "/a/b/c.txt";
+ File outFile = IOUtils.newFile(parent, path0);
+ assertTrue(outFile.getAbsolutePath().endsWith(path0),
+ "unexpected path: " + outFile.getAbsolutePath());
+ } finally {
+ assertTrue(parent.delete());
+ }
+ }
+
+ @Test
+ void testDisallowedPathTraversal() throws IOException {
+ final File parent = TempFile.createTempDirectory("path-traversal-test");
+ try {
+ final String path0 = "../a/b/c.txt";
+ Assertions.assertThrows(IOException.class, () -> IOUtils.newFile(parent, path0));
+ } finally {
+ assertTrue(parent.delete());
+ }
+ }
+
/**
* This returns 0 for the first call to skip and then reads
* as requested. This tests that the fallback to read() works.
diff --git a/src/documentation/content/xdocs/changes.xml b/src/documentation/content/xdocs/changes.xml
index c137381f78..ab248da55c 100644
--- a/src/documentation/content/xdocs/changes.xml
+++ b/src/documentation/content/xdocs/changes.xml
@@ -70,10 +70,11 @@
</p>
</section>
- <release version="5.4.2" date="2025-??-??">
+ <release version="5.5.0" date="2025-??-??">
<summary>
<summary-item>Upgrade batik dependency to 1.19</summary-item>
- <summary-item>Upgrade bouncycastle dependency to 1.80</summary-item>
+ <summary-item>Upgrade bouncycastle dependency to 1.81</summary-item>
+ <summary-item>Upgrade commons-codec dependency to 1.19.0</summary-item>
<summary-item>Upgrade commons-collections4 dependency to 4.5.0</summary-item>
<summary-item>Upgrade commons-io dependency to 2.20.0</summary-item>
<summary-item>Upgrade pdfbox dependency to 3.0.5</summary-item>