Browse Source

merge trunk

git-svn-id: https://svn.apache.org/repos/asf/poi/branches/hemf@1848906 13f79535-47bb-0310-9956-ffa450edef68
pull/133/head
Andreas Beeker 5 years ago
parent
commit
042b5ca545
80 changed files with 1743 additions and 876 deletions
  1. 157
    230
      build.xml
  2. 7
    0
      doap_POI.rdf
  3. 145
    0
      src/examples/src/org/apache/poi/xslf/usermodel/ChartFromScratch.java
  4. 140
    0
      src/examples/src/org/apache/poi/xwpf/usermodel/examples/ChartFromScratch.java
  5. 1
    0
      src/integrationtest/org/apache/poi/TestAllFiles.java
  6. 4
    5
      src/integrationtest/org/apache/poi/stress/XSSFFileHandler.java
  7. 26
    4
      src/java/org/apache/poi/ddf/EscherProperties.java
  8. 1
    1
      src/java/org/apache/poi/hpsf/VariantSupport.java
  9. 6
    1
      src/java/org/apache/poi/hpsf/wellknown/PropertyIDMap.java
  10. 2
    0
      src/java/org/apache/poi/hssf/model/InternalWorkbook.java
  11. 13
    6
      src/java/org/apache/poi/hssf/record/RecordInputStream.java
  12. 4
    4
      src/java/org/apache/poi/hssf/record/SSTRecord.java
  13. 5
    1
      src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java
  14. 6
    6
      src/java/org/apache/poi/hssf/record/SharedValueRecordBase.java
  15. 25
    1
      src/java/org/apache/poi/poifs/crypt/ChunkedCipherOutputStream.java
  16. 7
    1
      src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptor.java
  17. 13
    11
      src/java/org/apache/poi/poifs/filesystem/FileMagic.java
  18. 4
    2
      src/java/org/apache/poi/sl/draw/DrawBackground.java
  19. 2
    34
      src/java/org/apache/poi/sl/draw/DrawFreeformShape.java
  20. 61
    60
      src/java/org/apache/poi/sl/draw/DrawPaint.java
  21. 11
    3
      src/java/org/apache/poi/sl/draw/DrawSimpleShape.java
  22. 4
    2
      src/java/org/apache/poi/sl/draw/DrawTableShape.java
  23. 25
    22
      src/java/org/apache/poi/sl/draw/PathGradientPaint.java
  24. 14
    8
      src/java/org/apache/poi/sl/draw/geom/Context.java
  25. 24
    21
      src/java/org/apache/poi/sl/draw/geom/PresetGeometries.java
  26. 7
    8
      src/java/org/apache/poi/sl/usermodel/FreeformShape.java
  27. 9
    2
      src/java/org/apache/poi/ss/formula/SheetNameFormatter.java
  28. 73
    0
      src/java/org/apache/poi/ss/formula/SheetRangeAndWorkbookIndexFormatter.java
  29. 1
    1
      src/java/org/apache/poi/ss/formula/functions/MatrixFunction.java
  30. 3
    10
      src/java/org/apache/poi/ss/formula/ptg/Area3DPxg.java
  31. 3
    13
      src/java/org/apache/poi/ss/formula/ptg/Ref3DPxg.java
  32. 2
    2
      src/java/org/apache/poi/util/RecordFormatException.java
  33. 1
    1
      src/java/org/apache/poi/util/StringUtil.java
  34. 1
    1
      src/java/org/apache/poi/util/Units.java
  35. 1
    1
      src/ooxml/java/org/apache/poi/ooxml/POIXMLDocumentPart.java
  36. 31
    35
      src/ooxml/java/org/apache/poi/ooxml/extractor/CommandLineTextExtractor.java
  37. 1
    0
      src/ooxml/java/org/apache/poi/ooxml/util/POIXMLConstants.java
  38. 0
    2
      src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipHelper.java
  39. 1
    1
      src/ooxml/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java
  40. 7
    1
      src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureOutputStream.java
  41. 44
    2
      src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFChart.java
  42. 12
    3
      src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java
  43. 57
    0
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFChart.java
  44. 13
    0
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java
  45. 32
    1
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFreeformShape.java
  46. 28
    3
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSheet.java
  47. 0
    1
      src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java
  48. 17
    7
      src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java
  49. 2
    2
      src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFChart.java
  50. 2
    1
      src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java
  51. 3
    2
      src/ooxml/testcases/org/apache/poi/ooxml/TestPOIXMLProperties.java
  52. 3
    0
      src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java
  53. 6
    0
      src/ooxml/testcases/org/apache/poi/xddf/usermodel/TestNecessaryOOXMLClasses.java
  54. 1
    1
      src/ooxml/testcases/org/apache/poi/xdgf/extractor/TestXDGFVisioExtractor.java
  55. 3
    1
      src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestPPTX2PNG.java
  56. 24
    7
      src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java
  57. 21
    30
      src/ooxml/testcases/org/apache/poi/xssf/XSSFTestDataSamples.java
  58. 8
    0
      src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestXWPFWordExtractor.java
  59. 3
    1
      src/scratchpad/src/org/apache/poi/hslf/record/CurrentUserAtom.java
  60. 383
    12
      src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFAutoShape.java
  61. 24
    25
      src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFill.java
  62. 12
    252
      src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFreeformShape.java
  63. 12
    11
      src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java
  64. 3
    3
      src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java
  65. 1
    0
      src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java
  66. 14
    5
      src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java
  67. 0
    1
      src/scratchpad/testcases/org/apache/poi/hslf/model/AllHSLFModelTests.java
  68. 1
    1
      src/scratchpad/testcases/org/apache/poi/hslf/model/TestFreeform.java
  69. 1
    0
      src/scratchpad/testcases/org/apache/poi/hslf/usermodel/AllHSLFUserModelTests.java
  70. 1
    1
      src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBackground.java
  71. 81
    0
      src/testcases/org/apache/poi/poifs/filesystem/TestFileMagic.java
  72. 15
    0
      src/testcases/org/apache/poi/poifs/filesystem/TestPOIFSFileSystem.java
  73. 66
    0
      src/testcases/org/apache/poi/ss/formula/SheetRangeAndWorkbookIndexFormatterTest.java
  74. 2
    2
      src/testcases/org/apache/poi/ss/usermodel/TestExcelStyleDateFormatter.java
  75. BIN
      test-data/document/60316.docx
  76. BIN
      test-data/document/60316b.dotx
  77. BIN
      test-data/slideshow/customGeo.ppt
  78. BIN
      test-data/slideshow/customGeo.pptx
  79. BIN
      test-data/slideshow/keyframes.pptx
  80. BIN
      test-data/slideshow/pp40only.ppt

+ 157
- 230
build.xml View File

@@ -60,6 +60,10 @@ under the License.
<property name="jdk.version.class" value="1.8" description="JDK version of generated class files"/>
<property name="compile.debug" value="true"/>

<condition property="isIBMVM">
<contains string="${java.vendor}" substring="IBM" casesensitive="false"/>
</condition>

<!--
Logging is suppressed by default.
To redirect log output to console, run ant with -Dorg.apache.poi.util.POILogger=org.apache.poi.util.SystemOutLogger
@@ -342,17 +346,6 @@ under the License.
<propertyref name="scratchpad.ignore"/>
</propertyset>

<!-- these need to be set differently when running with Java 9 -->
<property name="java9addmods" value="-Dthis.is.a.dummy=true"/>
<property name="javadoc9addmods" value="-J-Dthis.is.a.dummy=true"/>
<property name="java9addmodsvalue" value="-Dthis.is.a.dummy=true"/>
<property name="java9addopens1" value="-Dthis.is.a.dummy=true"/>
<property name="java9addopens2" value="-Dthis.is.a.dummy=true"/>
<property name="java9addopens3" value="-Dthis.is.a.dummy=true"/>
<property name="java9addopens4" value="-Dthis.is.a.dummy=true"/>
<property name="java9addopens5" value="-Dthis.is.a.dummy=true"/>
<property name="java9addopens6" value="-Dthis.is.a.dummy=true"/>

<path id="main.classpath">
<pathelement location="${main.commons-logging.jar}"/>
<pathelement location="${main.commons-codec.jar}"/>
@@ -1180,6 +1173,59 @@ under the License.
</copy>
</target>

<macrodef name="poiunit" xmlns:jacoco="antlib:org.jacoco.ant">
<attribute name="failureproperty"/>
<attribute name="heap" default="512"/>
<attribute name="showoutput" default="false"/>
<attribute name="jacocodest" default="build/jacoco-dest.exec"/>
<element name="elements" implicit="true"/>
<sequential>
<local name="no.jit.sherlock"/>
<!-- see http://www-01.ibm.com/support/docview.wss?uid=swg21294023 on how to determine the method strings -->
<property name="no.jit.sherlock">
sun/java2d/pipe/AAShapePipe.renderTiles(Lsun/java2d/SunGraphics2D;Ljava/awt/Shape;Lsun/java2d/pipe/AATileGenerator;[I)V
sun/java2d/pipe/AlphaPaintPipe.renderPathTile(Ljava/lang/Object;[BIIIIII)V
java/awt/TexturePaintContext.getRaster(IIII)Ljava/awt/image/Raster;
</property>
<script language="javascript">
var before = project.getProperty("no.jit.sherlock");
project.setProperty("no.jit.sherlock", before.trim().replace(/ *(\S+) */g,"exclude={$1}").replace(/\s/g,","));
</script>

<local name="ooxml.lite.agent.exists"/>
<available property="ooxml.lite.agent.exists" file="${ooxml.lite.agent}"/>

<jacoco:coverage enabled="${coverage.enabled}" excludes="${coverage.excludes}" destfile="@{jacocodest}">
<junit printsummary="yes" fork="yes" forkmode="once" haltonfailure="${halt.on.test.failure}"
failureproperty="@{failureproperty}" showoutput="@{showoutput}">
<syspropertyset refid="junit.properties"/>
<sysproperty key="java.io.tmpdir" value="${tempdir}"/>
<jvmarg value="-Xmx@{heap}M"/>
<jvmarg value="-ea"/>

<!-- these need to be set differently when running with Java 9 -->
<jvmarg value="${java9addmods}" if:set="${java9addmods}" />
<jvmarg value="${java9addmodsvalue}" if:set="${java9addmodsvalue}" />
<jvmarg value="${java9addopens1}" if:set="${java9addopens1}" />
<jvmarg value="${java9addopens2}" if:set="${java9addopens2}" />
<jvmarg value="${java9addopens3}" if:set="${java9addopens3}" />
<jvmarg value="${java9addopens4}" if:set="${java9addopens4}" />
<jvmarg value="${java9addopens5}" if:set="${java9addopens5}" />
<jvmarg value="${java9addopens6}" if:set="${java9addopens6}" />

<jvmarg value="-javaagent:${ooxml.lite.agent}=${ooxml.lite.report}|${ooxml.lite.includes}" if:true="${ooxml.lite.agent.exists}"/>

<!-- jvmarg value="-Duser.timezone=UTC"/ -->
<jvmarg value="${file.leak.detector}" />
<jvmarg value="-Xjit:verbose={compileStart|compileEnd},vlog=build/jit.log,${no.jit.sherlock}" if:true="${isIBMVM}"/>
<formatter type="plain"/>
<formatter type="xml"/>
<elements/>
</junit>
</jacoco:coverage>
</sequential>
</macrodef>

<target name="retest-ooxml" depends="jar">
<delete dir="${ooxml.reports.test}"/>
<delete dir="${ooxml.output.test.dir}"/>
@@ -1219,39 +1265,23 @@ under the License.
<copy todir="${ooxml.output.dir}">
<fileset dir="${ooxml.resource1.dir}"/>
</copy>
<junit printsummary="yes" fork="yes" forkmode="once" haltonfailure="${halt.on.test.failure}"
failureproperty="ooxml.test.failed">
<poiunit failureproperty="ooxml.test.failed" heap="768">
<classpath>
<path refid="test.ooxml.lite.verify.classpath"/>
<path refid="test.jar.classpath"/>
</classpath>
<syspropertyset refid="junit.properties"/>
<sysproperty key="java.io.tmpdir" value="${tempdir}"/>
<jvmarg value="-Xmx768M"/>
<jvmarg value="-ea"/>
<jvmarg value="${java9addmods}" />
<jvmarg value="${java9addmodsvalue}" />
<jvmarg value="${java9addopens1}" />
<jvmarg value="${java9addopens2}" />
<jvmarg value="${java9addopens3}" />
<jvmarg value="${java9addopens4}" />
<jvmarg value="${java9addopens5}" />
<jvmarg value="${java9addopens6}" />
<!-- jvmarg value="-Duser.timezone=UTC"/ -->
<jvmarg value="${file.leak.detector}" />
<formatter type="plain"/>
<formatter type="xml"/>
<batchtest todir="${ooxml.reports.test}">
<fileset dir="${ooxml.src.test}">
<include name="**/${testpattern}.java"/>
<exclude name="**/TestUnfixedBugs.java"/>
<exclude name="**/All*Tests.java"/>
<exclude name="**/TestSignatureInfo.java"/>
<exclude name="**/${testexcludepattern}.java"/>
<patternset refid="exclude-scratchpad-test" if:true="${scratchpad.ignore}"/>
<include name="**/${testpattern}.java"/>
<exclude name="**/TestUnfixedBugs.java"/>
<exclude name="**/All*Tests.java"/>
<exclude name="**/TestSignatureInfo.java"/>
<exclude name="**/${testexcludepattern}.java"/>
<patternset refid="exclude-scratchpad-test" if:true="${scratchpad.ignore}"/>
</fileset>
</batchtest>
</junit>
</poiunit>
</target>

<target name="compile-excelant" depends="compile-main,compile-ooxml">
@@ -1306,6 +1336,7 @@ under the License.
<pathelement location="${main.ant.jar}"/>
<pathelement location="${scratchpad.output.dir}"/>
</classpath>
<exclude name="**/HeapDump**" if:true="${isIBMVM}"/>
</javac>
<!--copy todir="${integration.output.dir}">
<fileset dir="${integration.resource1.dir}"/>
@@ -1436,39 +1467,22 @@ under the License.
<target name="test-main" unless="main.test.notRequired"
depends="compile-main, -test-main-check,jacocotask" xmlns:jacoco="antlib:org.jacoco.ant"
description="tests POI classes that deal with the Microsoft Office binary (BIFF8) file formats (excludes OOXML)">
<jacoco:coverage enabled="${coverage.enabled}" excludes="${coverage.excludes}" destfile="build/jacoco-main.exec">
<junit fork="yes" forkmode="once" printsummary="yes" haltonfailure="${halt.on.test.failure}"
failureproperty="main.test.failed" showoutput="true">
<classpath refid="test.classpath"/>
<classpath refid="test.jar.classpath"/>
<syspropertyset refid="junit.properties"/>
<sysproperty key="java.io.tmpdir" value="${tempdir}"/>
<jvmarg value="-ea"/>
<jvmarg value="-Xmx256m"/>
<!-- jvmarg value="-Duser.timezone=UTC"/ -->
<jvmarg value="${java9addmods}" />
<jvmarg value="${java9addmodsvalue}" />
<jvmarg value="${java9addopens1}" />
<jvmarg value="${java9addopens2}" />
<jvmarg value="${java9addopens3}" />
<jvmarg value="${java9addopens4}" />
<jvmarg value="${java9addopens5}" />
<jvmarg value="${java9addopens6}" />
<jvmarg value="${file.leak.detector}" />
<formatter type="plain"/>
<formatter type="xml"/>
<batchtest todir="${main.reports.test}">
<fileset dir="${main.src.test}">
<include name="**/${testpattern}.java"/>
<exclude name="**/All*Tests.java"/>
<exclude name="**/TestUnfixedBugs.java"/>
<exclude name="**/TestcaseRecordInputStream.java"/>
<exclude name="**/${testexcludepattern}.java"/>
<patternset refid="exclude-scratchpad-test" if:true="${scratchpad.ignore}"/>
</fileset>
</batchtest>
</junit>
</jacoco:coverage>
<poiunit failureproperty="main.test.failed" heap="256" showoutput="true" jacocodest="build/jacoco-main.exec">
<classpath>
<path refid="test.classpath"/>
<path refid="test.jar.classpath"/>
</classpath>
<batchtest todir="${main.reports.test}">
<fileset dir="${main.src.test}">
<include name="**/${testpattern}.java"/>
<exclude name="**/All*Tests.java"/>
<exclude name="**/TestUnfixedBugs.java"/>
<exclude name="**/TestcaseRecordInputStream.java"/>
<exclude name="**/${testexcludepattern}.java"/>
<patternset refid="exclude-scratchpad-test" if:true="${scratchpad.ignore}"/>
</fileset>
</batchtest>
</poiunit>
<delete file="${main.testokfile}"/>
<antcall target="-test-main-write-testfile"/>
</target>
@@ -1500,45 +1514,23 @@ under the License.
</uptodate>
</target>

<target name="test-scratchpad" depends="compile-main,compile-scratchpad,-test-scratchpad-check,jacocotask,test-scratchpad-download-resources"
<target name="test-scratchpad" depends="compile-main,compile-scratchpad,-test-scratchpad-check,test-scratchpad-download-resources"
unless="scratchpad.test.notRequired" xmlns:jacoco="antlib:org.jacoco.ant"
description="test non-OOXML scratchpad classes">
<jacoco:coverage enabled="${coverage.enabled}" excludes="${coverage.excludes}" destfile="build/jacoco-scratchpad.exec">
<junit printsummary="yes" fork="yes" forkmode="once" haltonfailure="${halt.on.test.failure}"
failureproperty="scratchpad.test.failed">
<classpath refid="test.scratchpad.classpath"/>
<classpath refid="test.jar.classpath"/>
<syspropertyset refid="junit.properties"/>
<sysproperty key="java.io.tmpdir" value="${tempdir}"/>
<jvmarg value="-ea"/>
<!-- jvmarg value="-Duser.timezone=UTC"/ -->
<jvmarg value="${file.leak.detector}" />
<!--
YK: ensure that JUnit has enough memory to run tests.
Without the line below tests fail on Mac OS X with jdk-1.6.26
and on Windows with jdk-1.5.22
-->
<jvmarg value="-Xmx512m"/>
<jvmarg value="${java9addmods}" />
<jvmarg value="${java9addmodsvalue}" />
<jvmarg value="${java9addopens1}" />
<jvmarg value="${java9addopens2}" />
<jvmarg value="${java9addopens3}" />
<jvmarg value="${java9addopens4}" />
<jvmarg value="${java9addopens5}" />
<jvmarg value="${java9addopens6}" />
<formatter type="plain"/>
<formatter type="xml"/>
<batchtest todir="${scratchpad.reports.test}">
<fileset dir="${scratchpad.src.test}">
<include name="**/${testpattern}.java"/>
<exclude name="**/AllTests.java"/>
<exclude name="**/${testexcludepattern}.java"/>
<patternset refid="exclude-scratchpad-test" if:true="${scratchpad.ignore}"/>
</fileset>
</batchtest>
</junit>
</jacoco:coverage>
<poiunit failureproperty="scratchpad.test.failed" heap="512" jacocodest="build/jacoco-scratchpad.exec">
<classpath>
<path refid="test.scratchpad.classpath"/>
<path refid="test.jar.classpath"/>
</classpath>
<batchtest todir="${scratchpad.reports.test}">
<fileset dir="${scratchpad.src.test}">
<include name="**/${testpattern}.java"/>
<exclude name="**/AllTests.java"/>
<exclude name="**/${testexcludepattern}.java"/>
<patternset refid="exclude-scratchpad-test" if:true="${scratchpad.ignore}"/>
</fileset>
</batchtest>
</poiunit>
<delete file="${scratchpad.testokfile}"/>
<antcall target="-test-scratchpad-write-testfile"/>
</target>
@@ -1559,72 +1551,35 @@ under the License.
<attribute name="classpath"/>
<attribute name="type"/>
<sequential>
<jacoco:coverage enabled="${coverage.enabled}" excludes="${coverage.excludes}" destfile="build/jacoco-@{type}.exec">
<junit printsummary="yes" fork="yes" forkmode="once" haltonfailure="${halt.on.test.failure}"
failureproperty="ooxml.test.failed">
<classpath>
<path refid="@{classpath}"/>
<path refid="test.jar.classpath"/>
</classpath>
<syspropertyset refid="junit.properties"/>
<sysproperty key="java.io.tmpdir" value="${tempdir}"/>
<jvmarg value="-Xmx768M"/>
<jvmarg value="-ea"/>
<jvmarg value="-javaagent:${ooxml.lite.agent}=${ooxml.lite.report}|${ooxml.lite.includes}"/>
<jvmarg value="${java9addmods}" />
<jvmarg value="${java9addmodsvalue}" />
<jvmarg value="${java9addopens1}" />
<jvmarg value="${java9addopens2}" />
<jvmarg value="${java9addopens3}" />
<jvmarg value="${java9addopens4}" />
<jvmarg value="${java9addopens5}" />
<jvmarg value="${java9addopens6}" />
<!-- jvmarg value="-Duser.timezone=UTC"/ -->
<jvmarg value="${file.leak.detector}" />
<formatter type="plain"/>
<formatter type="xml"/>
<batchtest todir="${ooxml.reports.test}">
<fileset dir="${ooxml.src.test}">
<include name="**/${testpattern}.java"/>
<exclude name="**/TestUnfixedBugs.java"/>
<exclude name="**/All*Tests.java"/>
<exclude name="**/TestSignatureInfo.java"/>
<exclude name="**/${testexcludepattern}.java"/>
<patternset refid="exclude-scratchpad-test" if:true="${scratchpad.ignore}"/>
</fileset>
</batchtest>
</junit>
</jacoco:coverage>
<jacoco:coverage enabled="${coverage.enabled}" excludes="${coverage.excludes}" destfile="build/jacoco-@{type}-xmlsec.exec">
<junit printsummary="yes" fork="yes" forkmode="once" haltonfailure="${halt.on.test.failure}"
failureproperty="ooxml.xmlsec.test.failed">
<classpath>
<path refid="@{classpath}"/>
<path refid="test.jar.classpath"/>
<path refid="ooxml.xmlsec.classpath"/>
</classpath>
<syspropertyset refid="junit.properties"/>
<sysproperty key="java.io.tmpdir" value="${tempdir}"/>
<jvmarg value="-javaagent:${ooxml.lite.agent}=${ooxml.lite.report}|${ooxml.lite.includes}"/>
<jvmarg value="-Xmx768M"/>
<jvmarg value="-ea"/>
<jvmarg value="${java9addmods}" />
<jvmarg value="${java9addmodsvalue}" />
<jvmarg value="${java9addopens1}" />
<jvmarg value="${java9addopens2}" />
<jvmarg value="${java9addopens3}" />
<jvmarg value="${java9addopens4}" />
<jvmarg value="${java9addopens5}" />
<jvmarg value="${java9addopens6}" />
<formatter type="plain"/>
<formatter type="xml"/>
<batchtest todir="${ooxml.reports.test}">
<fileset dir="${ooxml.src.test}">
<include name="**/TestSignatureInfo.java"/>
</fileset>
</batchtest>
</junit>
</jacoco:coverage>
<poiunit failureproperty="ooxml.test.failed" heap="768" jacocodest="build/jacoco-@{type}.exec">
<classpath>
<path refid="@{classpath}"/>
<path refid="test.jar.classpath"/>
</classpath>
<batchtest todir="${ooxml.reports.test}">
<fileset dir="${ooxml.src.test}">
<include name="**/${testpattern}.java"/>
<exclude name="**/TestUnfixedBugs.java"/>
<exclude name="**/All*Tests.java"/>
<exclude name="**/TestSignatureInfo.java"/>
<exclude name="**/${testexcludepattern}.java"/>
<patternset refid="exclude-scratchpad-test" if:true="${scratchpad.ignore}"/>
</fileset>
</batchtest>
</poiunit>

<poiunit failureproperty="ooxml.xmlsec.test.failed" heap="768" jacocodest="build/jacoco-@{type}-xmlsec.exec">
<classpath>
<path refid="@{classpath}"/>
<path refid="test.jar.classpath"/>
<path refid="ooxml.xmlsec.classpath"/>
</classpath>
<batchtest todir="${ooxml.reports.test}">
<fileset dir="${ooxml.src.test}">
<include name="**/TestSignatureInfo.java"/>
</fileset>
</batchtest>
</poiunit>
</sequential>
</macrodef>

@@ -1650,34 +1605,16 @@ under the License.
unless="integration.test.notRequired" xmlns:jacoco="antlib:org.jacoco.ant">
<propertyreset name="org.apache.poi.util.POILogger" value="org.apache.poi.util.CommonsLogger"/>
<delete dir="build" includes="test-integration.log*"/>
<jacoco:coverage enabled="${coverage.enabled}" excludes="${coverage.excludes}" destfile="build/jacoco-integration.exec">
<junit printsummary="yes" fork="yes" forkmode="once" haltonfailure="${halt.on.test.failure}"
failureproperty="integration.test.failed" showoutput="true">
<classpath refid="test.integration.classpath"/>
<syspropertyset refid="junit.properties"/>
<sysproperty key="java.io.tmpdir" value="${tempdir}"/>
<jvmarg value="-ea"/>
<jvmarg value="-Xmx1512M"/>
<jvmarg value="-javaagent:${ooxml.lite.agent}=${ooxml.lite.report}|${ooxml.lite.includes}"/>
<jvmarg value="${java9addmods}" />
<jvmarg value="${java9addmodsvalue}" />
<jvmarg value="${java9addopens1}" />
<jvmarg value="${java9addopens2}" />
<jvmarg value="${java9addopens3}" />
<jvmarg value="${java9addopens4}" />
<jvmarg value="${java9addopens5}" />
<jvmarg value="${java9addopens6}" />
<formatter type="plain"/>
<formatter type="xml"/>
<batchtest todir="${integration.reports.test}">
<fileset dir="${integration.src.test}">
<include name="**/${testpattern}.java"/>
<exclude name="**/${testexcludepattern}.java"/>
<patternset refid="exclude-scratchpad-test" if:true="${scratchpad.ignore}"/>
</fileset>
</batchtest>
</junit>
</jacoco:coverage>
<poiunit failureproperty="integration.test.failed" heap="1512" showoutput="true" jacocodest="build/jacoco-integration.exec">
<classpath refid="test.integration.classpath"/>
<batchtest todir="${integration.reports.test}">
<fileset dir="${integration.src.test}">
<include name="**/${testpattern}.java"/>
<exclude name="**/${testexcludepattern}.java"/>
<patternset refid="exclude-scratchpad-test" if:true="${scratchpad.ignore}"/>
</fileset>
</batchtest>
</poiunit>
<delete file="${integration.testokfile}"/>
<antcall target="-test-integration-write-testfile"/>
</target>
@@ -1739,33 +1676,16 @@ under the License.

<target name="test-excelant" depends="compile-excelant,-test-excelant-check,jacocotask"
unless="excelant.test.notRequired" xmlns:jacoco="antlib:org.jacoco.ant">
<jacoco:coverage enabled="${coverage.enabled}" excludes="${coverage.excludes}" destfile="build/jacoco-excelant.exec">
<junit printsummary="yes" fork="yes" forkmode="once" haltonfailure="${halt.on.test.failure}"
failureproperty="excelant.test.failed">
<classpath refid="test.excelant.classpath"/>
<syspropertyset refid="junit.properties"/>
<sysproperty key="java.io.tmpdir" value="${tempdir}"/>
<jvmarg value="-ea"/>
<jvmarg value="${java9addmods}" />
<jvmarg value="${java9addmodsvalue}" />
<jvmarg value="${java9addopens1}" />
<jvmarg value="${java9addopens2}" />
<jvmarg value="${java9addopens3}" />
<jvmarg value="${java9addopens4}" />
<jvmarg value="${java9addopens5}" />
<jvmarg value="${java9addopens6}" />
<jvmarg value="${file.leak.detector}" />
<formatter type="plain"/>
<formatter type="xml"/>
<batchtest todir="${excelant.reports.test}">
<fileset dir="${excelant.src.test}">
<include name="**/${testpattern}.java"/>
<exclude name="**/${testexcludepattern}.java"/>
<patternset refid="exclude-scratchpad-test" if:true="${scratchpad.ignore}"/>
</fileset>
</batchtest>
</junit>
</jacoco:coverage>
<poiunit failureproperty="excelant.test.failed" jacocodest="build/jacoco-excelant.exec">
<classpath refid="test.excelant.classpath"/>
<batchtest todir="${excelant.reports.test}">
<fileset dir="${excelant.src.test}">
<include name="**/${testpattern}.java"/>
<exclude name="**/${testexcludepattern}.java"/>
<patternset refid="exclude-scratchpad-test" if:true="${scratchpad.ignore}"/>
</fileset>
</batchtest>
</poiunit>
<delete file="${excelant.testokfile}"/>
<antcall target="-test-excelant-write-testfile"/>
</target>
@@ -1791,6 +1711,9 @@ under the License.
<target name="docs" depends="init, -check-forrest-installed, -check-docs, javadocs, -forrest-docs"
unless="main.docs.notRequired"
description="Builds the POI website" />

<target name="site" depends="-forrest-docs"/>

<target name="-forrest-docs" depends="-check-forrest-installed, -check-docs"
unless="main.docs.notRequired" description="Builds the HTML pages of the POI website">
<exec executable="${env.FORREST_HOME}/bin/forrest" osfamily="unix"/>
@@ -1828,7 +1751,7 @@ under the License.
<include name="org/apache/poi/**"/>
</packageset>
<arg value="${javadoc9addmods}"/>
<arg value="${javadoc9addmods}" if:set="${javadoc9addmods}"/>

<doctitle><![CDATA[<h1>POI API Documentation</h1>]]></doctitle>
<bottom>
@@ -2113,6 +2036,7 @@ under the License.
sonar/*/src/**,
compile-lib/**,
ooxml-lib/**,
ooxml-testlib/**,
scripts/**,
TEST*,
*.ipr,
@@ -2303,7 +2227,10 @@ under the License.
</forbiddenapis>
</target>

<target name="findbugs" depends="jar">
<!-- disabling findbugs until jenkins is updated to a current IBM JDK
see https://stackoverflow.com/a/48561534/2066598
this should be replaced by spotbugs when available in the jenkins warnings plugin -->
<target name="findbugs" depends="jar" unless="${isIBMVM}">
<downloadfile src="${findbugs.url}" dest="${findbugs.jar}"/>

<property name="findbugs.home" value="build/findbugs" />
@@ -2453,7 +2380,7 @@ under the License.
<copy todir="${repo}">
<mappedresources>
<!-- 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"/>
</mappedresources>
</copy>

+ 7
- 0
doap_POI.rdf View File

@@ -35,6 +35,13 @@
<programming-language>Java</programming-language>
<category rdf:resource="https://projects.apache.org/category/content" />
<category rdf:resource="https://projects.apache.org/category/library" />
<release>
<Version>
<name>Apache POI 4.0.1</name>
<created>2018-12-03</created>
<revision>4.0.1</revision>
</Version>
</release>
<release>
<Version>
<name>Apache POI 4.0.0</name>

+ 145
- 0
src/examples/src/org/apache/poi/xslf/usermodel/ChartFromScratch.java View File

@@ -0,0 +1,145 @@
/*
* ====================================================================
* 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.xslf.usermodel;

import java.awt.geom.Rectangle2D;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xddf.usermodel.chart.AxisCrosses;
import org.apache.poi.xddf.usermodel.chart.AxisPosition;
import org.apache.poi.xddf.usermodel.chart.BarDirection;
import org.apache.poi.xddf.usermodel.chart.ChartTypes;
import org.apache.poi.xddf.usermodel.chart.LegendPosition;
import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
import org.apache.poi.xddf.usermodel.chart.XDDFChart;
import org.apache.poi.xddf.usermodel.chart.XDDFChartAxis;
import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;

/**
* Build a chart without reading template file
*/
public class ChartFromScratch {
private static void usage(){
System.out.println("Usage: BarChartExample <bar-chart-data.txt>");
System.out.println(" bar-chart-data.txt the model to set. First line is chart title, " +
"then go pairs {axis-label value}");
}

public static void main(String[] args) throws Exception {
if(args.length < 1) {
usage();
return;
}

try (BufferedReader modelReader = new BufferedReader(new FileReader(args[0]))) {

String chartTitle = modelReader.readLine(); // first line is chart title
String[] series = modelReader.readLine().split(",");

// Category Axis Data
List<String> listLanguages = new ArrayList<>(10);

// Values
List<Double> listCountries = new ArrayList<>(10);
List<Double> listSpeakers = new ArrayList<>(10);

// set model
String ln;
while((ln = modelReader.readLine()) != null) {
String[] vals = ln.split(",");
listCountries.add(Double.valueOf(vals[0]));
listSpeakers.add(Double.valueOf(vals[1]));
listLanguages.add(vals[2]);
}

String[] categories = listLanguages.toArray(new String[listLanguages.size()]);
Double[] values1 = listCountries.toArray(new Double[listCountries.size()]);
Double[] values2 = listSpeakers.toArray(new Double[listSpeakers.size()]);

try {

XMLSlideShow ppt = new XMLSlideShow();
XSLFSlide slide = ppt.createSlide();
XSLFChart chart = ppt.createChart();
Rectangle2D rect2D = new java.awt.Rectangle(XDDFChart.DEFAULT_X, XDDFChart.DEFAULT_Y,
XDDFChart.DEFAULT_WIDTH, XDDFChart.DEFAULT_HEIGHT);
slide.addChart(chart, rect2D);
setBarData(chart, chartTitle, series, categories, values1, values2);
// save the result
try (OutputStream out = new FileOutputStream("bar-chart-demo-output.pptx")) {
ppt.write(out);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
System.out.println("Done");
}

private static void setBarData(XSLFChart chart, String chartTitle, String[] series, String[] categories, Double[] values1, Double[] values2) {
// Use a category axis for the bottom axis.
XDDFChartAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setTitle(series[2]);
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setTitle(series[0]+","+series[1]);
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);

final int numOfPoints = categories.length;
final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1));
final String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, 2, 2));
final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0);
final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values1, valuesDataRange, 1);
values1[6] = 16.0; // if you ever want to change the underlying data
final XDDFNumericalDataSource<? extends Number> valuesData2 = XDDFDataSourcesFactory.fromArray(values2, valuesDataRange2, 2);


XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
XDDFBarChartData.Series series1 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData);
series1.setTitle(series[0], chart.setSheetTitle(series[0], 1));

XDDFBarChartData.Series series2 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData2);
series2.setTitle(series[1], chart.setSheetTitle(series[1], 2));

bar.setVaryColors(true);
bar.setBarDirection(BarDirection.COL);
chart.plot(bar);

XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.LEFT);
legend.setOverlay(false);

chart.setTitleText(chartTitle);
chart.setTitleOverlay(false);
}
}


+ 140
- 0
src/examples/src/org/apache/poi/xwpf/usermodel/examples/ChartFromScratch.java View File

@@ -0,0 +1,140 @@
/*
* ====================================================================
* 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.xwpf.usermodel.examples;

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xddf.usermodel.chart.AxisCrosses;
import org.apache.poi.xddf.usermodel.chart.AxisPosition;
import org.apache.poi.xddf.usermodel.chart.BarDirection;
import org.apache.poi.xddf.usermodel.chart.ChartTypes;
import org.apache.poi.xddf.usermodel.chart.LegendPosition;
import org.apache.poi.xddf.usermodel.chart.XDDFBarChartData;
import org.apache.poi.xddf.usermodel.chart.XDDFChart;
import org.apache.poi.xddf.usermodel.chart.XDDFChartAxis;
import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
import org.apache.poi.xddf.usermodel.chart.XDDFValueAxis;
import org.apache.poi.xwpf.usermodel.XWPFChart;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

/**
* Build a chart without reading template file
*/
public class ChartFromScratch {
private static void usage(){
System.out.println("Usage: BarChartExample <bar-chart-data.txt>");
System.out.println(" bar-chart-data.txt the model to set. First line is chart title, " +
"then go pairs {axis-label value}");
}

public static void main(String[] args) throws Exception {
if(args.length < 1) {
usage();
return;
}

try (BufferedReader modelReader = new BufferedReader(new FileReader(args[0]))) {

String chartTitle = modelReader.readLine(); // first line is chart title
String[] series = modelReader.readLine().split(",");

// Category Axis Data
List<String> listLanguages = new ArrayList<>(10);

// Values
List<Double> listCountries = new ArrayList<>(10);
List<Double> listSpeakers = new ArrayList<>(10);

// set model
String ln;
while((ln = modelReader.readLine()) != null) {
String[] vals = ln.split(",");
listCountries.add(Double.valueOf(vals[0]));
listSpeakers.add(Double.valueOf(vals[1]));
listLanguages.add(vals[2]);
}

String[] categories = listLanguages.toArray(new String[listLanguages.size()]);
Double[] values1 = listCountries.toArray(new Double[listCountries.size()]);
Double[] values2 = listSpeakers.toArray(new Double[listSpeakers.size()]);

try (XWPFDocument doc = new XWPFDocument()) {
XWPFChart chart = doc.createChart(XDDFChart.DEFAULT_WIDTH, XDDFChart.DEFAULT_HEIGHT);
setBarData(chart, chartTitle, series, categories, values1, values2);
// save the result
try (OutputStream out = new FileOutputStream("bar-chart-demo-output.docx")) {
doc.write(out);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
System.out.println("Done");
}

private static void setBarData(XWPFChart chart, String chartTitle, String[] series, String[] categories, Double[] values1, Double[] values2) {
// Use a category axis for the bottom axis.
XDDFChartAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
bottomAxis.setTitle(series[2]);
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
leftAxis.setTitle(series[0]+","+series[1]);
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);

final int numOfPoints = categories.length;
final String categoryDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 0, 0));
final String valuesDataRange = chart.formatRange(new CellRangeAddress(1, numOfPoints, 1, 1));
final String valuesDataRange2 = chart.formatRange(new CellRangeAddress(1, numOfPoints, 2, 2));
final XDDFDataSource<?> categoriesData = XDDFDataSourcesFactory.fromArray(categories, categoryDataRange, 0);
final XDDFNumericalDataSource<? extends Number> valuesData = XDDFDataSourcesFactory.fromArray(values1, valuesDataRange, 1);
values1[6] = 16.0; // if you ever want to change the underlying data
final XDDFNumericalDataSource<? extends Number> valuesData2 = XDDFDataSourcesFactory.fromArray(values2, valuesDataRange2, 2);


XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
XDDFBarChartData.Series series1 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData);
series1.setTitle(series[0], chart.setSheetTitle(series[0], 1));

XDDFBarChartData.Series series2 = (XDDFBarChartData.Series) bar.addSeries(categoriesData, valuesData2);
series2.setTitle(series[1], chart.setSheetTitle(series[1], 2));

bar.setVaryColors(true);
bar.setBarDirection(BarDirection.COL);
chart.plot(bar);

XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.LEFT);
legend.setOverlay(false);

chart.setTitleText(chartTitle);
chart.setTitleOverlay(false);
}
}


+ 1
- 0
src/integrationtest/org/apache/poi/TestAllFiles.java View File

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

+ 4
- 5
src/integrationtest/org/apache/poi/stress/XSSFFileHandler.java View File

@@ -35,7 +35,6 @@ import java.util.Iterator;
import java.util.Locale;
import java.util.Set;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;

import org.apache.poi.EncryptedDocumentException;
@@ -148,7 +147,7 @@ public class XSSFFileHandler extends SpreadsheetHandler {
}
private void exportToXML(XSSFWorkbook wb) throws SAXException,
ParserConfigurationException, TransformerException {
TransformerException {
for (XSSFMap map : wb.getCustomXMLMappings()) {
XSSFExportToXml exporter = new XSSFExportToXml(map);

@@ -165,7 +164,6 @@ public class XSSFFileHandler extends SpreadsheetHandler {
// zip-bomb
EXPECTED_ADDITIONAL_FAILURES.add("spreadsheet/54764.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-empty.xlsx");
// strict OOXML
@@ -185,18 +183,19 @@ public class XSSFFileHandler extends SpreadsheetHandler {
public void handleAdditional(File file) throws Exception {
// redirect stdout as the examples often write lots of text
PrintStream oldOut = System.out;
String testFile = file.getParentFile().getName() + "/" + file.getName();
try {
System.setOut(new NullPrintStream());
FromHowTo.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!",
EXPECTED_ADDITIONAL_FAILURES.contains(file.getParentFile().getName() + "/" + file.getName()));
EXPECTED_ADDITIONAL_FAILURES.contains(testFile));

} catch (OLE2NotOfficeXmlFileException e) {
// we have some files that are not actually OOXML and thus cannot be tested here
} catch (IllegalArgumentException | InvalidFormatException | POIXMLException | IOException e) {
if(!EXPECTED_ADDITIONAL_FAILURES.contains(file.getParentFile().getName() + "/" + file.getName())) {
if(!EXPECTED_ADDITIONAL_FAILURES.contains(testFile)) {
throw e;
}
} finally {

+ 26
- 4
src/java/org/apache/poi/ddf/EscherProperties.java View File

@@ -26,6 +26,7 @@ import java.util.Map;
*
* @author Glen Stampoultzis (glens at apache.org)
*/
@SuppressWarnings("WeakerAccess")
public final class EscherProperties {

// Property constants
@@ -117,6 +118,15 @@ public final class EscherProperties {
public static final short GEOMETRY__ADJUST8VALUE = 334;
public static final short GEOMETRY__ADJUST9VALUE = 335;
public static final short GEOMETRY__ADJUST10VALUE = 336;
public static final short GEOMETRY__PCONNECTIONSITES = 337;
public static final short GEOMETRY__PCONNECTIONSITESDIR = 338;
public static final short GEOMETRY__XLIMO = 339;
public static final short GEOMETRY__YLIMO = 340;
public static final short GEOMETRY__PADJUSTHANDLES = 341;
public static final short GEOMETRY__PGUIDES = 342;
public static final short GEOMETRY__PINSCRIBE = 343;
public static final short GEOMETRY__CXK = 344;
public static final short GEOMETRY__PFRAGMENTS = 345;
public static final short GEOMETRY__SHADOWok = 378;
public static final short GEOMETRY__3DOK = 379;
public static final short GEOMETRY__LINEOK = 380;
@@ -333,6 +343,9 @@ public final class EscherProperties {

private static final Map<Short, EscherPropertyMetaData> properties = initProps();

private EscherProperties() {
}

private static Map<Short, EscherPropertyMetaData> initProps() {
Map<Short, EscherPropertyMetaData> m = new HashMap<>();
addProp(m, TRANSFORM__ROTATION, "transform.rotation");
@@ -423,6 +436,15 @@ public final class EscherProperties {
addProp(m, GEOMETRY__ADJUST8VALUE, "geometry.adjust8value");
addProp(m, GEOMETRY__ADJUST9VALUE, "geometry.adjust9value");
addProp(m, GEOMETRY__ADJUST10VALUE, "geometry.adjust10value");
addProp(m, GEOMETRY__PCONNECTIONSITES, "geometry.pConnectionSites");
addProp(m, GEOMETRY__PCONNECTIONSITESDIR, "geometry.pConnectionSitesDir");
addProp(m, GEOMETRY__XLIMO, "geometry.xLimo");
addProp(m, GEOMETRY__YLIMO, "geometry.yLimo");
addProp(m, GEOMETRY__PADJUSTHANDLES, "geometry.pAdjustHandles");
addProp(m, GEOMETRY__PGUIDES, "geometry.pGuides");
addProp(m, GEOMETRY__PINSCRIBE, "geometry.pInscribe");
addProp(m, GEOMETRY__CXK, "geometry.cxk");
addProp(m, GEOMETRY__PFRAGMENTS, "geometry.pFragments");
addProp(m, GEOMETRY__SHADOWok, "geometry.shadowOK");
addProp(m, GEOMETRY__3DOK, "geometry.3dok");
addProp(m, GEOMETRY__LINEOK, "geometry.lineok");
@@ -641,20 +663,20 @@ public final class EscherProperties {
}

private static void addProp(Map<Short, EscherPropertyMetaData> m, int s, String propName) {
m.put(Short.valueOf((short) s), new EscherPropertyMetaData(propName));
m.put((short) s, new EscherPropertyMetaData(propName));
}

private static void addProp(Map<Short, EscherPropertyMetaData> m, int s, String propName, byte type) {
m.put(Short.valueOf((short) s), new EscherPropertyMetaData(propName, type));
m.put((short) s, new EscherPropertyMetaData(propName, type));
}

public static String getPropertyName(short propertyId) {
EscherPropertyMetaData o = properties.get(Short.valueOf(propertyId));
EscherPropertyMetaData o = properties.get(propertyId);
return o == null ? "unknown" : o.getDescription();
}

public static byte getPropertyType(short propertyId) {
EscherPropertyMetaData escherPropertyMetaData = properties.get(Short.valueOf(propertyId));
EscherPropertyMetaData escherPropertyMetaData = properties.get(propertyId);
return escherPropertyMetaData == null ? 0 : escherPropertyMetaData.getType();
}
}

+ 1
- 1
src/java/org/apache/poi/hpsf/VariantSupport.java View File

@@ -36,7 +36,7 @@ import org.apache.poi.util.POILogger;
* Supports reading and writing of variant data.<p>
*
* <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>
*

+ 6
- 1
src/java/org/apache/poi/hpsf/wellknown/PropertyIDMap.java View File

@@ -33,8 +33,11 @@ import org.apache.poi.hpsf.SummaryInformation;
* The methods {@link #getSummaryInformationProperties} and {@link
* #getDocumentSummaryInformationProperties} return singleton {@link
* 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.
*
* Trying to modify the map directly will cause exceptions
* {@link UnsupportedOperationException} to be thrown.
*/
public class PropertyIDMap implements Map<Long,String> {

@@ -490,11 +493,13 @@ public class PropertyIDMap implements Map<Long,String> {

@Override
public String put(Long key, String value) {
//noinspection ConstantConditions
return idMap.put(key, value);
}

@Override
public String remove(Object key) {
//noinspection ConstantConditions
return idMap.remove(key);
}


+ 2
- 0
src/java/org/apache/poi/hssf/model/InternalWorkbook.java View File

@@ -2276,6 +2276,8 @@ public final class InternalWorkbook {

/**
* Only for internal calls - code based on this is not supported ...
*
* @return The list of records.
*/
@Internal
public WorkbookRecordList getWorkbookRecordList() {

+ 13
- 6
src/java/org/apache/poi/hssf/record/RecordInputStream.java View File

@@ -33,8 +33,9 @@ import org.apache.poi.util.LittleEndianInputStream;
import org.apache.poi.util.RecordFormatException;

/**
* Title: Record Input Stream<P>
* Description: Wraps a stream and provides helper methods for the construction of records.<P>
* Title: Record Input Stream
*
* Description: Wraps a stream and provides helper methods for the construction of records.
*/
public final class RecordInputStream implements LittleEndianInput {

@@ -142,6 +143,15 @@ public final class RecordInputStream implements LittleEndianInput {
_nextSid = readNextSid();
}

static LittleEndianInput getLEI(InputStream is) {
if (is instanceof LittleEndianInput) {
// accessing directly is an optimisation
return (LittleEndianInput) is;
}
// less optimal, but should work OK just the same. Often occurs in junit tests.
return new LittleEndianInputStream(is);
}

/**
* @return the number of bytes available in the current BIFF record
* @see #remaining()
@@ -295,12 +305,9 @@ public final class RecordInputStream implements LittleEndianInput {
return _dataInput.readUShort();
}

/**
*
* @return a double - might return NaN
*/
@Override
public double readDouble() {
// YK: Excel doesn't write NaN but instead converts the cell type into {@link CellType#ERROR}.
return Double.longBitsToDouble(readLong());
}

+ 4
- 4
src/java/org/apache/poi/hssf/record/SSTRecord.java View File

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

+ 5
- 1
src/java/org/apache/poi/hssf/record/SharedFormulaRecord.java View File

@@ -77,7 +77,7 @@ public final class SharedFormulaRecord extends SharedValueRecordBase {

public String toString()
{
StringBuffer buffer = new StringBuffer();
StringBuilder buffer = new StringBuilder();

buffer.append("[SHARED FORMULA (").append(HexDump.intToHex(sid)).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.
*/
public Ptg[] getFormulaTokens(FormulaRecord formula) {

+ 6
- 6
src/java/org/apache/poi/hssf/record/SharedValueRecordBase.java View File

@@ -42,6 +42,8 @@ public abstract class SharedValueRecordBase extends StandardRecord {

/**
* reads only the range (1 {@link CellRangeAddress8Bit}) from the stream
*
* @param in The interface for reading the record data.
*/
public SharedValueRecordBase(LittleEndianInput in) {
_range = new CellRangeAddress8Bit(in);
@@ -99,14 +101,12 @@ public abstract class SharedValueRecordBase extends StandardRecord {
&& 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 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()
*/
public final boolean isFirstCell(int rowIx, int colIx) {

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

@@ -99,6 +99,13 @@ public abstract class ChunkedCipherOutputStream extends FilterOutputStream {
return initCipherForBlock(cipher, block, lastChunk);
}

// helper method to break a recursion loop introduced because of an IBMJCE bug, i.e. not resetting on Cipher.doFinal()
@Internal
protected Cipher initCipherForBlockNoFlush(Cipher existing, int block, boolean lastChunk)
throws IOException, GeneralSecurityException {
return initCipherForBlock(cipher, block, lastChunk);
}

protected abstract Cipher initCipherForBlock(Cipher existing, int block, boolean lastChunk)
throws IOException, GeneralSecurityException;

@@ -212,13 +219,30 @@ public abstract class ChunkedCipherOutputStream extends FilterOutputStream {
* @throws IllegalBlockSizeException
* @throws ShortBufferException
*/
protected int invokeCipher(int posInChunk, boolean doFinal) throws GeneralSecurityException {
protected int invokeCipher(int posInChunk, boolean doFinal) throws GeneralSecurityException, IOException {
byte plain[] = (plainByteFlags.isEmpty()) ? null : chunk.clone();

int ciLen = (doFinal)
? cipher.doFinal(chunk, 0, posInChunk, chunk)
: cipher.update(chunk, 0, posInChunk, chunk);

if (doFinal && "IBMJCE".equals(cipher.getProvider().getName()) && "RC4".equals(cipher.getAlgorithm())) {
// workaround for IBMs cipher not resetting on doFinal

int index = (int)(pos >> chunkBits);
boolean lastChunk;
if (posInChunk==0) {
index--;
posInChunk = chunk.length;
lastChunk = false;
} else {
// pad the last chunk
lastChunk = true;
}

cipher = initCipherForBlockNoFlush(cipher, index, lastChunk);
}

if (plain != null) {
int i = plainByteFlags.nextSetBit(0);
while (i >= 0 && i < posInChunk) {

+ 7
- 1
src/java/org/apache/poi/poifs/crypt/cryptoapi/CryptoAPIEncryptor.java View File

@@ -207,9 +207,15 @@ public class CryptoAPIEncryptor extends Encryptor implements Cloneable {
protected Cipher initCipherForBlock(Cipher cipher, int block, boolean lastChunk)
throws IOException, GeneralSecurityException {
flush();
return initCipherForBlockNoFlush(cipher, block, lastChunk);
}

@Override
protected Cipher initCipherForBlockNoFlush(Cipher existing, int block, boolean lastChunk)
throws GeneralSecurityException {
EncryptionInfo ei = getEncryptionInfo();
SecretKey sk = getSecretKey();
return CryptoAPIDecryptor.initCipherForBlock(cipher, block, ei, sk, Cipher.ENCRYPT_MODE);
return CryptoAPIDecryptor.initCipherForBlock(existing, block, ei, sk, Cipher.ENCRYPT_MODE);
}

@Override

+ 13
- 11
src/java/org/apache/poi/poifs/filesystem/FileMagic.java View File

@@ -78,7 +78,7 @@ public enum FileMagic {
/** PDF document */
PDF("%PDF"),
/** 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}),
// keep UNKNOWN always as last enum!
/** UNKNOWN magic */
@@ -101,17 +101,8 @@ public enum FileMagic {

public static FileMagic valueOf(byte[] magic) {
for (FileMagic fm : values()) {
int i=0;
boolean found = true;
for (byte[] ma : fm.magic) {
for (byte m : ma) {
byte d = magic[i++];
if (!(d == m || (m == 0x70 && (d == 0x10 || d == 0x20 || d == 0x40)))) {
found = false;
break;
}
}
if (found) {
if (findMagic(ma, magic)) {
return fm;
}
}
@@ -119,6 +110,17 @@ public enum FileMagic {
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>

+ 4
- 2
src/java/org/apache/poi/sl/draw/DrawBackground.java View File

@@ -17,6 +17,8 @@

package org.apache.poi.sl.draw;

import static org.apache.poi.sl.draw.DrawPaint.fillPaintWorkaround;

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Paint;
@@ -59,10 +61,10 @@ public class DrawBackground extends DrawShape {
if(fill != null) {
graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, anchor);
graphics.setPaint(fill);
graphics.fill(anchor2);
fillPaintWorkaround(graphics, anchor2);
}
}
protected Background<?,?> getShape() {
return (Background<?,?>)shape;
}

+ 2
- 34
src/java/org/apache/poi/sl/draw/DrawFreeformShape.java View File

@@ -17,43 +17,11 @@

package org.apache.poi.sl.draw;

import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.poi.sl.draw.geom.Outline;
import org.apache.poi.sl.draw.geom.Path;
import org.apache.poi.sl.usermodel.*;
import org.apache.poi.sl.usermodel.FreeformShape;

@SuppressWarnings("WeakerAccess")
public class DrawFreeformShape extends DrawAutoShape {
public DrawFreeformShape(FreeformShape<?,?> shape) {
super(shape);
}

protected Collection<Outline> computeOutlines(Graphics2D graphics) {
List<Outline> lst = new ArrayList<>();
FreeformShape<?,?> fsh = (FreeformShape<?, ?>) getShape();
Path2D sh = fsh.getPath();

AffineTransform tx = (AffineTransform)graphics.getRenderingHint(Drawable.GROUP_TRANSFORM);
if (tx == null) {
tx = new AffineTransform();
}

java.awt.Shape canvasShape = tx.createTransformedShape(sh);

FillStyle fs = fsh.getFillStyle();
StrokeStyle ss = fsh.getStrokeStyle();
Path path = new Path(fs != null, ss != null);
lst.add(new Outline(canvasShape, path));
return lst;
}

@Override
protected TextShape<?,? extends TextParagraph<?,?,? extends TextRun>> getShape() {
return (TextShape<?,? extends TextParagraph<?,?,? extends TextRun>>)shape;
}
}

+ 61
- 60
src/java/org/apache/poi/sl/draw/DrawPaint.java View File

@@ -23,13 +23,17 @@ import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.Paint;
import java.awt.RadialGradientPaint;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
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.ColorStyle;
@@ -197,28 +201,17 @@ public class DrawPaint {

@Override
public int getShade() {
int shade = orig.getShade();
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;
}
return scale(orig.getShade(), PaintModifier.DARKEN_LESS, PaintModifier.DARKEN);
}

@Override
public int getTint() {
int tint = orig.getTint();
switch (modifier) {
case LIGHTEN:
return Math.min(100000, Math.max(0,tint)+40000);
case LIGHTEN_LESS:
return Math.min(100000, Math.max(0,tint)+20000);
default:
return tint;
}
return scale(orig.getTint(), PaintModifier.LIGHTEN_LESS, PaintModifier.LIGHTEN);
}

private int scale(int value, PaintModifier lessModifier, PaintModifier moreModifier) {
int delta = (modifier == lessModifier ? 20000 : (modifier == moreModifier ? 40000 : 0));
return Math.min(100000, Math.max(0,value)+delta);
}
};

@@ -300,7 +293,7 @@ public class DrawPaint {
Color result = color.getColor();

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, 1, color.getSatMod(), color.getSatOff());
applyHslModOff(hsl, 2, color.getLumMod(), color.getLumOff());
@@ -344,7 +337,7 @@ public class DrawPaint {
* @param mod the modulation 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) {
mod = 100000;
}
@@ -363,7 +356,7 @@ public class DrawPaint {
*
* 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();
if (shade == -1) {
return;
@@ -380,7 +373,7 @@ public class DrawPaint {
* For a tint, the equation is luminance * %tint + (1-%tint).
* (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();
if (tint == -1) {
return;
@@ -403,70 +396,63 @@ public class DrawPaint {
}

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());

double diagonal = Math.sqrt(h * h + w * w);
Point2D p1 = new Point2D.Double(x + w / 2 - diagonal / 2, y + h / 2);
p1 = at.transform(p1, null);

Point2D p2 = new Point2D.Double(x + w, y + h / 2);
p2 = at.transform(p2, null);
double diagonal = Math.sqrt(Math.pow(anchor.getWidth(),2) + Math.pow(anchor.getHeight(),2));
final Point2D p1 = at.transform(new Point2D.Double(anchor.getCenterX() - diagonal / 2, anchor.getCenterY()), null);
final Point2D p2 = at.transform(new Point2D.Double(anchor.getMaxX(), anchor.getCenterY()), null);

// snapToAnchor(p1, anchor);
// snapToAnchor(p2, anchor);

if (p1.equals(p2)) {
// gradient paint on the same point throws an exception ... and doesn't make sense
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);
// 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);
}


@SuppressWarnings("WeakerAccess")
protected Paint createRadialGradientPaint(GradientPaint fill, Graphics2D graphics) {
Rectangle2D anchor = DrawShape.getAnchor(graphics, shape);

Point2D pCenter = new Point2D.Double(anchor.getX() + anchor.getWidth()/2,
anchor.getY() + anchor.getHeight()/2);
final Point2D pCenter = new Point2D.Double(anchor.getCenterX(), anchor.getCenterY());

float radius = (float)Math.max(anchor.getWidth(), anchor.getHeight());
final float radius = (float)Math.max(anchor.getWidth(), anchor.getHeight());

float[] fractions = fill.getGradientFractions();
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);
return safeFractions((f,c)->new RadialGradientPaint(pCenter,radius,f,c), fill);
}

@SuppressWarnings({"WeakerAccess", "unused"})
protected Paint createPathGradientPaint(GradientPaint fill, Graphics2D graphics) {
// currently we ignore an eventually center setting

return safeFractions(PathGradientPaint::new, fill);
}

private Paint safeFractions(BiFunction<float[],Color[],Paint> init, GradientPaint fill) {
float[] fractions = fill.getGradientFractions();
Color[] colors = new Color[fractions.length];
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])));
}

final Color[] colors = new Color[m.size()];
if (fractions.length != m.size()) {
fractions = new float[m.size()];
}

int i=0;
for (ColorStyle fc : fill.getGradientColors()) {
colors[i++] = applyColorTransform(fc);
for (Map.Entry<Float,Color> me : m.entrySet()) {
fractions[i] = me.getKey();
colors[i] = me.getValue();
i++;
}

return new PathGradientPaint(colors, fractions);
return init.apply(fractions, colors);
}

/**
@@ -620,4 +606,19 @@ public class DrawPaint {
return (float)(1.055d * Math.pow(linRGB / 100000d, 1.0d/2.4d) - 0.055d);
}
}


static void fillPaintWorkaround(Graphics2D graphics, Shape shape) {
// the ibm jdk has a rendering/JIT bug, which throws an AIOOBE in
// TexturePaintContext$Int.setRaster(TexturePaintContext.java:476)
// this usually doesn't happen while debugging, because JIT doesn't jump in then.
try {
graphics.fill(shape);
} catch (ArrayIndexOutOfBoundsException e) {
LOG.log(POILogger.WARN, "IBM JDK failed with TexturePaintContext AIOOBE - try adding the following to the VM parameter:\n" +
"-Xjit:exclude={sun/java2d/pipe/AlphaPaintPipe.renderPathTile(Ljava/lang/Object;[BIIIIII)V} and " +
"search for 'JIT Problem Determination for IBM SDK using -Xjit' (http://www-01.ibm.com/support/docview.wss?uid=swg21294023) " +
"for how to add/determine further excludes", e);
}
}
}

+ 11
- 3
src/java/org/apache/poi/sl/draw/DrawSimpleShape.java View File

@@ -17,6 +17,8 @@

package org.apache.poi.sl.draw;

import static org.apache.poi.sl.draw.DrawPaint.fillPaintWorkaround;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics2D;
@@ -87,7 +89,7 @@ public class DrawSimpleShape extends DrawShape {
graphics.setPaint(fillMod);
java.awt.Shape s = o.getOutline();
graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s);
graphics.fill(s);
fillPaintWorkaround(graphics, s);
}
}
}
@@ -327,7 +329,7 @@ public class DrawSimpleShape extends DrawShape {
graphics.setPaint(shadowColor);

if(fill != null && p.isFilled()){
graphics.fill(s);
fillPaintWorkaround(graphics, s);
} else if (line != null && p.isStroked()) {
graphics.draw(s);
}
@@ -410,14 +412,20 @@ public class DrawSimpleShape extends DrawShape {
}
for (Path p : geom) {

double w = p.getW(), h = p.getH(), scaleX = Units.toPoints(1), scaleY = scaleX;
double w = p.getW(), h = p.getH(), scaleX, scaleY;
if (w == -1) {
w = Units.toEMU(anchor.getWidth());
scaleX = Units.toPoints(1);
} else if (anchor.getWidth() == 0) {
scaleX = 1;
} else {
scaleX = anchor.getWidth() / w;
}
if (h == -1) {
h = Units.toEMU(anchor.getHeight());
scaleY = Units.toPoints(1);
} else if (anchor.getHeight() == 0) {
scaleY = 1;
} else {
scaleY = anchor.getHeight() / h;
}

+ 4
- 2
src/java/org/apache/poi/sl/draw/DrawTableShape.java View File

@@ -17,6 +17,8 @@

package org.apache.poi.sl.draw;

import static org.apache.poi.sl.draw.DrawPaint.fillPaintWorkaround;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Paint;
@@ -83,8 +85,8 @@ public class DrawTableShape extends DrawShape {
Paint fillPaint = drawPaint.getPaint(graphics, tc.getFillStyle().getPaint());
graphics.setPaint(fillPaint);
Rectangle2D cellAnc = tc.getAnchor();
graphics.fill(cellAnc);
fillPaintWorkaround(graphics, cellAnc);
for (BorderEdge edge : BorderEdge.values()) {
StrokeStyle stroke = tc.getBorderStyle(edge);
if (stroke == null) {

+ 25
- 22
src/java/org/apache/poi/sl/draw/PathGradientPaint.java View File

@@ -23,21 +23,24 @@ import java.awt.MultipleGradientPaint.CycleMethod;
import java.awt.geom.*;
import java.awt.image.*;

import org.apache.poi.util.Internal;

@Internal
class PathGradientPaint implements Paint {

// http://asserttrue.blogspot.de/2010/01/how-to-iimplement-custom-paint-in-50.html
protected final Color colors[];
protected final float fractions[];
protected final int capStyle;
protected final int joinStyle;
protected final int transparency;
private final Color[] colors;
private final float[] fractions;
private final int capStyle;
private final int joinStyle;
private final int transparency;

public PathGradientPaint(Color colors[], float fractions[]) {
this(colors,fractions,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
PathGradientPaint(float[] fractions, Color[] colors) {
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.fractions = fractions.clone();
this.capStyle = capStyle;
@@ -66,26 +69,26 @@ class PathGradientPaint implements Paint {
}

class PathGradientContext implements PaintContext {
protected final Rectangle deviceBounds;
protected final Rectangle2D userBounds;
final Rectangle deviceBounds;
final Rectangle2D userBounds;
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
* in the draw/-content method, so we need to postpone the setting/creation as long as possible
**/
protected final Shape shape;
protected final PaintContext pCtx;
protected final int gradientSteps;
final PaintContext pCtx;
final int gradientSteps;
WritableRaster raster;

public PathGradientContext(
ColorModel cm
, Rectangle deviceBounds
, Rectangle2D userBounds
, AffineTransform xform
, RenderingHints hints
PathGradientContext(
ColorModel cm
, Rectangle deviceBounds
, Rectangle2D userBounds
, AffineTransform xform
, RenderingHints hints
) {
shape = (Shape)hints.get(Drawable.GRADIENT_SHAPE);
if (shape == null) {
@@ -139,7 +142,7 @@ class PathGradientPaint implements Paint {
return childRaster;
}

protected int getGradientSteps(Shape gradientShape) {
int getGradientSteps(Shape gradientShape) {
Rectangle rect = gradientShape.getBounds();
int lower = 1;
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();
raster = cm.createCompatibleWritableRaster((int)deviceBounds.getWidth(), (int)deviceBounds.getHeight());
BufferedImage img = new BufferedImage(cm, raster, false, null);
@@ -168,7 +171,7 @@ class PathGradientPaint implements Paint {
graphics.transform(xform);

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--) {
img2.getPixel(i, 0, rgb);

+ 14
- 8
src/java/org/apache/poi/sl/draw/geom/Context.java View File

@@ -22,11 +22,18 @@ package org.apache.poi.sl.draw.geom;
import java.awt.geom.Rectangle2D;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

public class Context {
final Map<String, Double> _ctx = new HashMap<>();
final IAdjustableShape _props;
final Rectangle2D _anchor;
private static final Pattern DOUBLE_PATTERN = Pattern.compile(
"[\\x00-\\x20]*[+-]?(NaN|Infinity|((((\\p{Digit}+)(\\.)?((\\p{Digit}+)?)" +
"([eE][+-]?(\\p{Digit}+))?)|(\\.(\\p{Digit}+)([eE][+-]?(\\p{Digit}+))?)|" +
"(((0[xX](\\p{XDigit}+)(\\.)?)|(0[xX](\\p{XDigit}+)?(\\.)(\\p{XDigit}+)))" +
"[pP][+-]?(\\p{Digit}+)))[fFdD]?))[\\x00-\\x20]*");

private final Map<String, Double> _ctx = new HashMap<>();
private final IAdjustableShape _props;
private final Rectangle2D _anchor;
public Context(CustomGeometry geom, Rectangle2D anchor, IAdjustableShape props){
_props = props;
@@ -39,23 +46,22 @@ public class Context {
}
}

public Rectangle2D getShapeAnchor(){
Rectangle2D getShapeAnchor(){
return _anchor;
}

public Guide getAdjustValue(String name){
Guide getAdjustValue(String name){
// ignore HSLF props for now ... the results with default value are usually better - see #59004
return (_props.getClass().getName().contains("hslf")) ? null : _props.getAdjustValue(name);
}

public double getValue(String key){
if(key.matches("(\\+|-)?\\d+")){
if(DOUBLE_PATTERN.matcher(key).matches()){
return Double.parseDouble(key);
}

Double val = _ctx.get(key);
// BuiltInGuide throws IllegalArgumentException if key is not defined
return (val != null) ? val : evaluate(BuiltInGuide.valueOf("_"+key));
return _ctx.containsKey(key) ? _ctx.get(key) : evaluate(BuiltInGuide.valueOf("_"+key));
}

public double evaluate(Formula fmla){

+ 24
- 21
src/java/org/apache/poi/sl/draw/geom/PresetGeometries.java View File

@@ -27,12 +27,12 @@ import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.EventFilter;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import javax.xml.transform.stream.StreamSource;

import org.apache.poi.sl.draw.binding.CTCustomGeometry2D;
import org.apache.poi.util.POILogFactory;
@@ -61,27 +61,30 @@ public class PresetGeometries extends LinkedHashMap<String, CustomGeometry> {
};
XMLInputFactory staxFactory = StaxHelper.newXMLInputFactory();
XMLEventReader staxReader = staxFactory.createXMLEventReader(is);
XMLEventReader staxFiltRd = staxFactory.createFilteredReader(staxReader, startElementFilter);
// ignore StartElement:
/* XMLEvent evDoc = */ staxFiltRd.nextEvent();
// JAXB:
JAXBContext jaxbContext = JAXBContext.newInstance(BINDING_PACKAGE);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
XMLStreamReader streamReader = staxFactory.createXMLStreamReader(new StreamSource(is));
try {
// ignore StartElement:
streamReader.nextTag();

long cntElem = 0;
while (staxFiltRd.peek() != null) {
StartElement evRoot = (StartElement)staxFiltRd.peek();
String name = evRoot.getName().getLocalPart();
JAXBElement<CTCustomGeometry2D> el = unmarshaller.unmarshal(staxReader, CTCustomGeometry2D.class);
CTCustomGeometry2D cus = el.getValue();
cntElem++;
if(containsKey(name)) {
LOG.log(POILogger.WARN, "Duplicate definition of " + name);
// JAXB:
JAXBContext jaxbContext = JAXBContext.newInstance(BINDING_PACKAGE);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

long cntElem = 0;
while (streamReader.hasNext() && streamReader.nextTag() == XMLStreamConstants.START_ELEMENT) {
String name = streamReader.getLocalName();
JAXBElement<CTCustomGeometry2D> el = unmarshaller.unmarshal(streamReader, CTCustomGeometry2D.class);
CTCustomGeometry2D cus = el.getValue();
cntElem++;

if (containsKey(name)) {
LOG.log(POILogger.WARN, "Duplicate definition of " + name);
}
put(name, new CustomGeometry(cus));
}
put(name, new CustomGeometry(cus));
}
} finally {
streamReader.close();
}
}
/**

+ 7
- 8
src/java/org/apache/poi/sl/usermodel/FreeformShape.java View File

@@ -24,16 +24,15 @@ public interface FreeformShape<
P extends TextParagraph<S,P,? extends TextRun>
> extends AutoShape<S,P> {
/**
* Gets the shape path.
* <p>
* The path is translated in the shape's coordinate system, i.e.
* freeform.getPath().getBounds2D() equals to freeform.getAnchor()
* (small discrepancies are possible due to rounding errors)
* </p>
* Gets the shape path.<p>
*
* The path is translated in the shape's coordinate system, i.e.
* freeform.getPath2D().getBounds2D() equals to freeform.getAnchor()
* (small discrepancies are possible due to rounding errors)
*
* @return the path
*/
Path2D.Double getPath();
Path2D getPath();

/**
* Set the shape path
@@ -41,5 +40,5 @@ public interface FreeformShape<
* @param path shape outline
* @return the number of points written
*/
int setPath(Path2D.Double path);
int setPath(Path2D path);
}

+ 9
- 2
src/java/org/apache/poi/ss/formula/SheetNameFormatter.java View File

@@ -59,6 +59,7 @@ public final class SheetNameFormatter {
* @param rawSheetName - sheet name
* @deprecated use <code>appendFormat(StringBuilder out, String rawSheetName)</code> instead
*/
@Deprecated
public static void appendFormat(StringBuffer out, String rawSheetName) {
boolean needsQuotes = needsDelimiting(rawSheetName);
if(needsQuotes) {
@@ -73,6 +74,7 @@ public final class SheetNameFormatter {
/**
* @deprecated use <code>appendFormat(StringBuilder out, String workbookName, String rawSheetName)</code> instead
*/
@Deprecated
public static void appendFormat(StringBuffer out, String workbookName, String rawSheetName) {
boolean needsQuotes = needsDelimiting(workbookName) || needsDelimiting(rawSheetName);
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();
for(int i=0; i<len; 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();
if(len < 1) {
throw new RuntimeException("Zero length string is an invalid sheet name");

+ 73
- 0
src/java/org/apache/poi/ss/formula/SheetRangeAndWorkbookIndexFormatter.java 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;
}
}

+ 1
- 1
src/java/org/apache/poi/ss/formula/functions/MatrixFunction.java View File

@@ -63,7 +63,7 @@ public abstract class MatrixFunction implements Function{
i = 0;
j++;
}
matrix[j][i++] = aVector;
if (j < matrix.length) matrix[j][i++] = aVector;
}
}

+ 3
- 10
src/java/org/apache/poi/ss/formula/ptg/Area3DPxg.java View File

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

SheetRangeAndWorkbookIndexFormatter.format(sb, externalWorkbookNumber, firstSheetName, lastSheetName);
sb.append('!');
sb.append(formatReferenceAsString());
return sb.toString();

+ 3
- 13
src/java/org/apache/poi/ss/formula/ptg/Ref3DPxg.java View File

@@ -18,7 +18,7 @@
package org.apache.poi.ss.formula.ptg;

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.util.CellReference;
import org.apache.poi.util.LittleEndianOutput;
@@ -101,18 +101,8 @@ public final class Ref3DPxg extends RefPtgBase implements Pxg3D {

public String toFormulaString() {
StringBuilder sb = new StringBuilder(64);
if (externalWorkbookNumber >= 0) {
sb.append('[');
sb.append(externalWorkbookNumber);
sb.append(']');
}
if (firstSheetName != null) {
SheetNameFormatter.appendFormat(sb, firstSheetName);
}
if (lastSheetName != null) {
sb.append(':');
SheetNameFormatter.appendFormat(sb, lastSheetName);
}

SheetRangeAndWorkbookIndexFormatter.format(sb, externalWorkbookNumber, firstSheetName, lastSheetName);
sb.append('!');
sb.append(formatReferenceAsString());
return sb.toString();

+ 2
- 2
src/java/org/apache/poi/util/RecordFormatException.java View File

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

+ 1
- 1
src/java/org/apache/poi/util/StringUtil.java View File

@@ -698,7 +698,7 @@ public class StringUtil {
final String prefix;

// #61881 - for now we only check the first char
if (len > 0 && string[offset] == 0 && string[offset+1] == 0) {
if (len > 0 && offset < (string.length - 1) && string[offset] == 0 && string[offset+1] == 0) {
newOffset = offset+2;
prefix = "?";


+ 1
- 1
src/java/org/apache/poi/util/Units.java View File

@@ -127,7 +127,7 @@ public class Units {
points /= MASTER_DPI;
return points;
}
public static int pointsToMaster(double points) {
points *= MASTER_DPI;
points /= POINT_DPI;

+ 1
- 1
src/ooxml/java/org/apache/poi/ooxml/POIXMLDocumentPart.java View File

@@ -615,7 +615,7 @@ public class POIXMLDocumentPart {
protected void read(POIXMLFactory factory, Map<PackagePart, POIXMLDocumentPart> context) throws OpenXML4JException {
PackagePart pp = getPackagePart();

if (pp.getContentType().equals(XWPFRelation.TEMPLATE.getContentType())) {
if (pp.getContentType().equals(XWPFRelation.GLOSSARY_DOCUMENT.getContentType())) {
logger.log(POILogger.WARN,
"POI does not currently support template.main+xml (glossary) parts. " +
"Skipping this part for now.");

+ 31
- 35
src/ooxml/java/org/apache/poi/ooxml/extractor/CommandLineTextExtractor.java View File

@@ -22,41 +22,37 @@ import org.apache.poi.extractor.POITextExtractor;

/**
* A command line wrapper around {@link ExtractorFactory}, useful
* for when debugging.
* for when debugging.
*/
public class CommandLineTextExtractor {
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) {
System.out.println(DIVIDER);

File f = new File(arg);
System.out.println(f);

POITextExtractor extractor =
ExtractorFactory.createExtractor(f);
try {
POITextExtractor metadataExtractor =
extractor.getMetadataTextExtractor();

System.out.println(" " + DIVIDER);
String metaData = metadataExtractor.getText();
System.out.println(metaData);
System.out.println(" " + DIVIDER);
String text = extractor.getText();
System.out.println(text);
System.out.println(DIVIDER);
System.out.println("Had " + metaData.length() + " characters of metadata and " + text.length() + " characters of text");
} finally {
extractor.close();
}
}
}
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) {
System.out.println(DIVIDER);

File f = new File(arg);
System.out.println(f);

try (POITextExtractor extractor = ExtractorFactory.createExtractor(f)) {
POITextExtractor metadataExtractor =
extractor.getMetadataTextExtractor();

System.out.println(" " + DIVIDER);
String metaData = metadataExtractor.getText();
System.out.println(metaData);
System.out.println(" " + DIVIDER);
String text = extractor.getText();
System.out.println(text);
System.out.println(DIVIDER);
System.out.println("Had " + metaData.length() + " characters of metadata and " + text.length() + " characters of text");
}
}
}
}

+ 1
- 0
src/ooxml/java/org/apache/poi/ooxml/util/POIXMLConstants.java View File

@@ -20,6 +20,7 @@ package org.apache.poi.ooxml.util;
public class POIXMLConstants {
public static final String FEATURE_LOAD_DTD_GRAMMAR = "http://apache.org/xml/features/nonvalidating/load-dtd-grammar";
public static final String FEATURE_LOAD_EXTERNAL_DTD = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
public static final String FEATURE_DISALLOW_DOCTYPE_DECL = "http://apache.org/xml/features/disallow-doctype-decl";
public static final String PROPERTY_ENTITY_EXPANSION_LIMIT = "http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit";
public static final String PROPERTY_SECURITY_MANAGER = "http://apache.org/xml/properties/security-manager";
}

+ 0
- 2
src/ooxml/java/org/apache/poi/openxml4j/opc/internal/ZipHelper.java View File

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

+ 1
- 1
src/ooxml/java/org/apache/poi/openxml4j/util/ZipInputStreamZipEntrySource.java View File

@@ -38,7 +38,7 @@ public class ZipInputStreamZipEntrySource implements ZipEntrySource {
/**
* 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
* work with the entries at-will.
*/

+ 7
- 1
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureOutputStream.java View File

@@ -20,6 +20,7 @@ package org.apache.poi.poifs.crypt.dsig;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.security.Security;
import java.security.Signature;
import java.security.SignatureException;

@@ -35,7 +36,12 @@ import org.apache.poi.poifs.crypt.HashAlgorithm;
@Override
public void init() throws GeneralSecurityException {
final String provider = isMSCapi(key) ? "SunMSCAPI" : "SunRsaSign";
signature = Signature.getInstance(algo.ecmaString+"withRSA", provider);
if (Security.getProvider(provider) != null) {
signature = Signature.getInstance(algo.ecmaString + "withRSA", provider);
} else {
signature = Signature.getInstance(algo.ecmaString + "withRSA");
}

signature.initSign(key);
}


+ 44
- 2
src/ooxml/java/org/apache/poi/xddf/usermodel/chart/XDDFChart.java View File

@@ -53,6 +53,7 @@ import org.apache.poi.xddf.usermodel.text.XDDFTextBody;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFTable;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;
@@ -81,6 +82,27 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumns;

@Beta
public abstract class XDDFChart extends POIXMLDocumentPart implements TextContainer {
/**
* default width of chart in emu
*/
public static final int DEFAULT_WIDTH = 500000;

/**
* default height of chart in emu
*/
public static final int DEFAULT_HEIGHT = 500000;
/**
* default x-coordinate of chart in emu
*/
public static final int DEFAULT_X = 10;

/**
* default y-coordinate value of chart in emu
*/
public static final int DEFAULT_Y = 10;
/**
* Underlying workbook
*/
@@ -712,10 +734,29 @@ public abstract class XDDFChart extends POIXMLDocumentPart implements TextContai
XSSFRow row = this.getRow(sheet, 0);
XSSFCell cell = this.getCell(row, column);
cell.setCellValue(title);
this.updateSheetTable(sheet.getTables().get(0).getCTTable(), title, column);
CTTable ctTable = this.getSheetTable(sheet);
this.updateSheetTable(ctTable, title, column);
return new CellReference(sheet.getSheetName(), 0, column, true, true);
}

/**
* this method will check whether sheet have table
* in case table size zero then create new table and add table columns element
* @param sheet
* @return table object
*/
private CTTable getSheetTable(XSSFSheet sheet) {
if(sheet.getTables().size() == 0)
{
XSSFTable newTable = sheet.createTable(null);
newTable.getCTTable().addNewTableColumns();
sheet.getTables().add(newTable);
}
return sheet.getTables().get(0).getCTTable();
}

/**
* this method update column header of sheet into table
*
@@ -729,7 +770,8 @@ public abstract class XDDFChart extends POIXMLDocumentPart implements TextContai
private void updateSheetTable(CTTable ctTable, String title, int index) {
CTTableColumns tableColumnList = ctTable.getTableColumns();
CTTableColumn column = null;
for( int i = 0; tableColumnList.getCount() < index; i++) {
int columnCount = tableColumnList.getTableColumnList().size()-1;
for( int i = columnCount; i < index; i++) {
column = tableColumnList.addNewTableColumn();
column.setId(i);
}

+ 12
- 3
src/ooxml/java/org/apache/poi/xslf/usermodel/XMLSlideShow.java View File

@@ -302,14 +302,23 @@ public class XMLSlideShow extends POIXMLDocument
* Create a blank chart on the given slide.
*/
public XSLFChart createChart(XSLFSlide slide) {
XSLFChart chart = createChart();
slide.addRelation(null, XSLFRelation.CHART, chart);
return chart;
}
/**
* This method is used to create template for chart XML.
* @return Xslf chart object
* @since POI 4.0.2
*/
public XSLFChart createChart() {
int chartIdx = findNextAvailableFileNameIndex(XSLFRelation.CHART, _charts.size() + 1);
XSLFChart chart = (XSLFChart) createRelationship(XSLFRelation.CHART, XSLFFactory.getInstance(), chartIdx, true).getDocumentPart();
slide.addRelation(null, XSLFRelation.CHART, chart);
chart.setChartIndex(chartIdx);
_charts.add(chart);
return chart;
}

/**
* Return notes slide for the specified slide or create new if it does not exist yet.
*/
@@ -416,7 +425,7 @@ public class XMLSlideShow extends POIXMLDocument
* Return all the charts in the slideshow
*/
public List<XSLFChart> getCharts() {
return _charts;
return Collections.unmodifiableList(_charts);
}

/**

+ 57
- 0
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFChart.java View File

@@ -19,16 +19,28 @@

package org.apache.poi.xslf.usermodel;

import java.awt.geom.Rectangle2D;
import java.io.IOException;

import javax.xml.namespace.QName;

import org.apache.poi.ooxml.POIXMLFactory;
import org.apache.poi.ooxml.POIXMLRelation;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
import org.apache.poi.util.Beta;
import org.apache.poi.xddf.usermodel.chart.XDDFChart;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTTitle;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObjectData;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPoint2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
import org.openxmlformats.schemas.drawingml.x2006.main.CTTransform2D;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrame;
import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFrameNonVisual;

/**
* Represents a Chart in a .pptx presentation
@@ -36,6 +48,8 @@ import org.openxmlformats.schemas.drawingml.x2006.main.CTTextBody;
@Beta
public final class XSLFChart extends XDDFChart {

private static String CHART_URI = "http://schemas.openxmlformats.org/drawingml/2006/chart";

/**
* Construct a PresentationML chart.
*/
@@ -90,4 +104,47 @@ public final class XSLFChart extends XDDFChart {
};
}
}

/**
* method to add graphic frame for XSLF chart
*
* @param shapeId shape id
* @param rID relation id
* @param anchor size and location of chart
* @return graphic frame object
* @since POI 4.0.2
*/
static CTGraphicalObjectFrame prototype(int shapeId, String rID, Rectangle2D anchor) {
CTGraphicalObjectFrame frame = CTGraphicalObjectFrame.Factory.newInstance();
CTGraphicalObjectFrameNonVisual nvGr = frame.addNewNvGraphicFramePr();

CTNonVisualDrawingProps cnv = nvGr.addNewCNvPr();
cnv.setName("Chart " + shapeId);
cnv.setId(shapeId);
nvGr.addNewCNvGraphicFramePr().addNewGraphicFrameLocks().setNoGrp(true);
nvGr.addNewNvPr();

CTTransform2D xfrm = frame.addNewXfrm();

CTPoint2D off = xfrm.addNewOff();
off.setX((int)anchor.getX());
off.setY((int)anchor.getY());

CTPositiveSize2D ext = xfrm.addNewExt();
ext.setCx((int)anchor.getWidth());
ext.setCy((int)anchor.getHeight());

xfrm.setExt(ext);
xfrm.setOff(off);

CTGraphicalObjectData gr = frame.addNewGraphic().addNewGraphicData();
XmlCursor grCur = gr.newCursor();
grCur.toNextToken();
grCur.beginElement(new QName(CHART_URI, "chart"));
grCur.insertAttributeWithValue("id", PackageRelationshipTypes.CORE_PROPERTIES_ECMA376_NS, rID);
grCur.dispose();

gr.setUri(CHART_URI);
return frame;
}
}

+ 13
- 0
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFDrawing.java View File

@@ -107,6 +107,19 @@ public class XSLFDrawing {
return shape;
}

/**
* This method will add chart into slide's graphic frame
*
* @param rID relation id of chart
* @param rect2D Chart Bounding values
* @since POI 4.0.2
*/
public void addChart(String rID, Rectangle2D rect2D) {
CTGraphicalObjectFrame sp = _spTree.addNewGraphicFrame();
sp.set(XSLFChart.prototype(_sheet.allocateShapeId(), rID, rect2D));
}


public XSLFObjectShape createOleShape(String pictureRel) {
CTGraphicalObjectFrame sp = _spTree.addNewGraphicFrame();
sp.set(XSLFObjectShape.prototype(_sheet.allocateShapeId(), pictureRel));

+ 32
- 1
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFFreeformShape.java View File

@@ -24,6 +24,12 @@ import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Rectangle2D;

import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.apache.poi.ooxml.POIXMLTypeLoader;
import org.apache.poi.sl.draw.geom.CustomGeometry;
import org.apache.poi.sl.draw.geom.PresetGeometries;
import org.apache.poi.sl.usermodel.FreeformShape;
import org.apache.poi.util.Beta;
import org.apache.poi.util.POILogFactory;
@@ -31,6 +37,7 @@ import org.apache.poi.util.POILogger;
import org.apache.poi.util.Units;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.openxmlformats.schemas.drawingml.x2006.main.CTAdjPoint2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTCustomGeometry2D;
import org.openxmlformats.schemas.drawingml.x2006.main.CTGeomRect;
@@ -61,7 +68,7 @@ public class XSLFFreeformShape extends XSLFAutoShape
}

@Override
public int setPath(final Path2D.Double path) {
public int setPath(final Path2D path) {
final CTPath2D ctPath = CTPath2D.Factory.newInstance();

final Rectangle2D bounds = path.getBounds2D();
@@ -117,6 +124,30 @@ public class XSLFFreeformShape extends XSLFAutoShape
return numPoints;
}

/**
* @return definition of the shape geometry
*/
@Override
public CustomGeometry getGeometry() {
final XmlObject xo = getShapeProperties();
if (!(xo instanceof CTShapeProperties)) {
return null;
}

XmlOptions xop = new XmlOptions(POIXMLTypeLoader.DEFAULT_XML_OPTIONS);
xop.setSaveOuter();

XMLStreamReader staxReader = ((CTShapeProperties)xo).getCustGeom().newXMLStreamReader(xop);
CustomGeometry custGeo = PresetGeometries.convertCustomGeometry(staxReader);
try {
staxReader.close();
} catch (XMLStreamException e) {
LOG.log(POILogger.WARN,
"An error occurred while closing a Custom Geometry XML Stream Reader: " + e.getMessage());
}

return custGeo;
}

@Override
public Path2D.Double getPath() {

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

@@ -20,6 +20,7 @@ import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -52,6 +53,7 @@ import org.apache.poi.util.IOUtils;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.Units;
import org.apache.poi.xddf.usermodel.chart.XDDFChart;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
@@ -306,14 +308,13 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
throw new IllegalArgumentException("pictureData needs to be of type XSLFPictureData");
}
RelationPart rp = addRelation(null, XSLFRelation.IMAGES, (XSLFPictureData)pictureData);
XSLFObjectShape sh = getDrawing().createOleShape(rp.getRelationship().getId());
CTOleObject oleObj = sh.getCTOleObject();
Dimension dim = pictureData.getImageDimension();
oleObj.setImgW(Units.toEMU(dim.getWidth()));
oleObj.setImgH(Units.toEMU(dim.getHeight()));

getShapes().add(sh);
sh.setParent(this);
return sh;
@@ -719,4 +720,28 @@ implements XSLFShapeContainer, Sheet<XSLFShape,XSLFTextParagraph> {
return (ph == null) ? null : new XSLFPlaceholderDetails(ph);
}

/**
* this method will add chart into slide
* with default height, width, x and y
* @param chart xslf chart object
* @since POI 4.0.2
*/
public void addChart(XSLFChart chart) {
Rectangle2D rect2D = new java.awt.Rectangle(XDDFChart.DEFAULT_X, XDDFChart.DEFAULT_Y,
XDDFChart.DEFAULT_WIDTH, XDDFChart.DEFAULT_HEIGHT);

this.addChart(chart, rect2D);
}

/**
* this method will add chart into slide
* with given height, width, x and y
* @param chart xslf chart object
* @since POI 4.0.2
*/
public void addChart(XSLFChart chart, Rectangle2D rect2D) {
RelationPart rp = addRelation(null, XSLFRelation.CHART, chart);
getDrawing().addChart(rp.getRelationship().getId(), rect2D);
}

}

+ 0
- 1
src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFSimpleShape.java View File

@@ -716,7 +716,6 @@ public abstract class XSLFSimpleShape extends XSLFShape
}

/**
*
* @return definition of the shape geometry
*/
@Override

+ 17
- 7
src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java View File

@@ -32,6 +32,7 @@ import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;

import org.apache.commons.compress.archivers.zip.Zip64Mode;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.poi.openxml4j.opc.OPCPackage;
@@ -51,13 +52,7 @@ import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.SheetVisibility;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal;
import org.apache.poi.util.NotImplemented;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.util.Removal;
import org.apache.poi.util.TempFile;
import org.apache.poi.util.*;
import org.apache.poi.xssf.model.SharedStringsTable;
import org.apache.poi.xssf.usermodel.XSSFChartSheet;
import org.apache.poi.xssf.usermodel.XSSFSheet;
@@ -117,6 +112,8 @@ public class SXSSFWorkbook implements Workbook {
*/
private final SharedStringsTable _sharedStringSource;

private Zip64Mode zip64Mode = Zip64Mode.AsNeeded;

/**
* Construct a new workbook with default row window size
*/
@@ -250,6 +247,7 @@ public class SXSSFWorkbook implements Workbook {
}
}
}

/**
* Construct an empty workbook and specify the window for row access.
* <p>
@@ -290,6 +288,16 @@ public class SXSSFWorkbook implements Workbook {
_randomAccessWindowSize = rowAccessWindowSize;
}

/**
* @param zip64Mode {@link Zip64Mode}
*
* @since 4.0.3
*/
@Beta
public void setZip64Mode(Zip64Mode zip64Mode) {
this.zip64Mode = zip64Mode;
}

/**
* Get whether temp files should be compressed.
*
@@ -298,6 +306,7 @@ public class SXSSFWorkbook implements Workbook {
public boolean isCompressTempFiles() {
return _compressTmpFiles;
}

/**
* Set whether temp files should be compressed.
* <p>
@@ -377,6 +386,7 @@ public class SXSSFWorkbook implements Workbook {

protected void injectData(ZipEntrySource zipEntrySource, OutputStream out) throws IOException {
ZipArchiveOutputStream zos = new ZipArchiveOutputStream(out);
zos.setUseZip64(zip64Mode);
try {
Enumeration<? extends ZipArchiveEntry> en = zipEntrySource.getEntries();
while (en.hasMoreElements()) {

+ 2
- 2
src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFChart.java View File

@@ -39,12 +39,12 @@ public class XWPFChart extends XDDFChart {
/**
* default width of chart in emu
*/
public static final int DEFAULT_WIDTH = 500000;
public static final int DEFAULT_WIDTH = XDDFChart.DEFAULT_WIDTH;

/**
* default height of chart in emu
*/
public static final int DEFAULT_HEIGHT = 500000;
public static final int DEFAULT_HEIGHT = XDDFChart.DEFAULT_HEIGHT;

// lazy initialization
private Long checksum;

+ 2
- 1
src/ooxml/java/org/apache/poi/xwpf/usermodel/XWPFDocument.java View File

@@ -58,6 +58,7 @@ import org.apache.poi.util.Internal;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
import org.apache.poi.wp.usermodel.HeaderFooterType;
import org.apache.poi.xddf.usermodel.chart.XDDFChart;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlException;
@@ -1672,7 +1673,7 @@ public class XWPFDocument extends POIXMLDocument implements Document, IBody {
* @since POI 4.0.0
*/
public XWPFChart createChart() throws InvalidFormatException, IOException {
return createChart(XWPFChart.DEFAULT_WIDTH, XWPFChart.DEFAULT_HEIGHT);
return createChart(XDDFChart.DEFAULT_WIDTH, XDDFChart.DEFAULT_HEIGHT);
}

/**

+ 3
- 2
src/ooxml/testcases/org/apache/poi/ooxml/TestPOIXMLProperties.java View File

@@ -19,6 +19,7 @@ package org.apache.poi.ooxml;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -89,7 +90,7 @@ public final class TestPOIXMLProperties {
XSSFWorkbook newWorkbook =
XSSFTestDataSamples.writeOutAndReadBack(workbook);
workbook.close();
assertTrue(workbook != newWorkbook);
assertNotSame(workbook, newWorkbook);


POIXMLProperties newProps = newWorkbook.getProperties();
@@ -158,7 +159,7 @@ public final class TestPOIXMLProperties {
p = ctProps.getPropertyArray(3);
assertEquals("{D5CDD505-2E9C-101B-9397-08002B2CF9AE}", p.getFmtid());
assertEquals("test-4", p.getName());
assertEquals(true, p.getBool());
assertTrue(p.getBool());
assertEquals(5, p.getPid());
wb2.close();

+ 3
- 0
src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java View File

@@ -60,6 +60,7 @@ import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.dom.DOMSignContext;

import org.apache.jcp.xml.dsig.internal.dom.DOMSignedInfo;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.POIDataSamples;
import org.apache.poi.POITestCase;
import org.apache.poi.ooxml.util.DocumentHelper;
@@ -682,6 +683,8 @@ public class TestSignatureInfo {
si.confirmSignature();
boolean b = si.verifySignature();
assertTrue("Signature not correctly calculated for " + ha, b);
} catch (EncryptedDocumentException e) {
Assume.assumeTrue(e.getMessage().startsWith("Export Restrictions"));
} finally {
if (pkg != null) {
pkg.close();

+ 6
- 0
src/ooxml/testcases/org/apache/poi/xddf/usermodel/TestNecessaryOOXMLClasses.java View File

@@ -87,6 +87,10 @@ public class TestNecessaryOOXMLClasses {
Assert.assertNotNull(ctLblAlgn);
CTDashStopList ctDashStopList = CTDashStopList.Factory.newInstance();
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");
Assert.assertNotNull(e1);
@@ -100,6 +104,8 @@ public class TestNecessaryOOXMLClasses {
Assert.assertNotNull(e5);
STMarkerStyle.Enum e6 = STMarkerStyle.Enum.forString("circle");
Assert.assertNotNull(e6);
STDispBlanksAs.Enum e7 = STDispBlanksAs.Enum.forString("span");
Assert.assertNotNull(e7);

CTTextBulletTypefaceFollowText ctTextBulletTypefaceFollowText = CTTextBulletTypefaceFollowText.Factory.newInstance();
Assert.assertNotNull(ctTextBulletTypefaceFollowText);

+ 1
- 1
src/ooxml/testcases/org/apache/poi/xdgf/extractor/TestXDGFVisioExtractor.java View File

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

+ 3
- 1
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestPPTX2PNG.java View File

@@ -47,7 +47,9 @@ public class TestPPTX2PNG {
private static final POIDataSamples samples = POIDataSamples.getSlideShowInstance();
private static final File basedir = null;
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," +
"customGeo.pptx, customGeo.ppt";


+ 24
- 7
src/ooxml/testcases/org/apache/poi/xslf/usermodel/TestXSLFSlide.java View File

@@ -20,6 +20,7 @@ import static org.apache.poi.sl.TestCommonSL.sameColor;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

@@ -34,7 +35,7 @@ import org.junit.Test;
* @author Yegor Kozlov
*/
public class TestXSLFSlide {
@Test
public void testReadShapes() throws IOException {
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");
@@ -101,7 +102,7 @@ public class TestXSLFSlide {
XSLFTable tbl = (XSLFTable)shapes4.get(0);
assertEquals(3, tbl.getNumberOfColumns());
assertEquals(6, tbl.getNumberOfRows());
ppt.close();
}

@@ -116,7 +117,7 @@ public class TestXSLFSlide {
assertFalse(slide.getFollowMasterGraphics());
slide.setFollowMasterGraphics(true);
assertTrue(slide.getFollowMasterGraphics());
ppt.close();
}

@@ -174,7 +175,7 @@ public class TestXSLFSlide {
XSLFPictureShape sh4 = (XSLFPictureShape)shapes2.get(1);
XSLFPictureShape srcPic = (XSLFPictureShape)src.getSlides().get(4).getShapes().get(1);
assertArrayEquals(sh4.getPictureData().getData(), srcPic.getPictureData().getData());
ppt.close();
}

@@ -191,7 +192,23 @@ public class TestXSLFSlide {
}
}
assertEquals(30, ppt.getSlides().size());
ppt.close();
}
}
}

@Test
public void testCreateChart() throws IOException {
XMLSlideShow ppt = new XMLSlideShow();
XSLFSlide slide = ppt.createSlide();
XSLFChart chart = ppt.createChart();
assertNotNull(chart);

slide.addChart(chart);
assertEquals(XSLFRelation.CHART.getContentType(), chart.getPackagePart().getContentType());

String partName = slide.getRelationPartById("rId2").getDocumentPart().getPackagePart().getPartName().getName();
assertEquals(partName, chart.getPackagePart().getPartName().getName());

ppt.close();
}
}

+ 21
- 30
src/ooxml/testcases/org/apache/poi/xssf/XSSFTestDataSamples.java View File

@@ -70,7 +70,7 @@ public class XSSFTestDataSamples {
* @param wb the workbook to write
* @param testName a fragment of the filename
* @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 {
final File file = getOutputFile(testName);
@@ -104,7 +104,9 @@ public class XSSFTestDataSamples {
file = TempFile.createTempFile(testName, ".xlsx");
}
if (file.exists()) {
file.delete();
if(!file.delete()) {
throw new IOException("Could not delete file " + file);
}
}
return file;
}
@@ -114,7 +116,7 @@ public class XSSFTestDataSamples {
*
* @param wb the workbook to write
* @return the memory buffer
* @throws IOException
* @throws IOException If writing the file fails
*/
public static <R extends Workbook> ByteArrayOutputStream writeOut(R wb) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream(8192);
@@ -137,7 +139,7 @@ public class XSSFTestDataSamples {
* 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.
*
* @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)
* @return workbook location
* @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
* @return the memory buffer
* @throws IOException
* @throws RuntimeException If writing the file fails
*/
public static <R extends Workbook> ByteArrayOutputStream writeOutAndClose(R wb) {
try {
ByteArrayOutputStream out = writeOut(wb);
// Do not close the workbook if there was a problem writing the workbook
wb.close();
return out;
}
catch (final IOException e) {
throw new RuntimeException(e);
}
public static <R extends Workbook> ByteArrayOutputStream writeOutAndClose(R wb) throws IOException {
ByteArrayOutputStream out = writeOut(wb);
// Do not close the workbook if there was a problem writing the workbook
wb.close();
return out;
}

/**
@@ -183,12 +180,14 @@ public class XSSFTestDataSamples {
*
* @param file the workbook file to read and delete
* @return the read back workbook
* @throws IOException
* @throws IOException If reading or deleting the file fails
*/
public static XSSFWorkbook readBackAndDelete(File file) throws IOException {
XSSFWorkbook wb = readBack(file);
// 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;
}

@@ -198,16 +197,12 @@ public class XSSFTestDataSamples {
*
* @param file the workbook file to read
* @return the read back workbook
* @throws IOException
* @throws IOException If reading the file fails
*/
public static XSSFWorkbook readBack(File file) throws IOException {
InputStream in = new FileInputStream(file);
try {
try (InputStream in = new FileInputStream(file)) {
return new XSSFWorkbook(in);
}
finally {
in.close();
}
}

/**
@@ -216,17 +211,13 @@ public class XSSFTestDataSamples {
*
* @param out the output stream to read back from
* @return the read back workbook
* @throws IOException
* @throws IOException If reading the file fails
*/
public static XSSFWorkbook readBack(ByteArrayOutputStream out) throws IOException {
InputStream is = new ByteArrayInputStream(out.toByteArray());
out.close();
try {
try (InputStream is = new ByteArrayInputStream(out.toByteArray())) {
out.close();
return new XSSFWorkbook(is);
}
finally {
is.close();
}
}

/**

+ 8
- 0
src/ooxml/testcases/org/apache/poi/xwpf/extractor/TestXWPFWordExtractor.java View File

@@ -452,4 +452,12 @@ public class TestXWPFWordExtractor extends TestCase {
//once we add processing for this, we can change this to contains
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");
}
}

+ 3
- 1
src/scratchpad/src/org/apache/poi/hslf/record/CurrentUserAtom.java View File

@@ -20,6 +20,8 @@

package org.apache.poi.hslf.record;

import static org.apache.poi.hslf.usermodel.HSLFSlideShow.PP95_DOCUMENT;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
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
// read it
if(_contents.length < 28) {
boolean isPP95 = dir.hasEntry("PP40");
boolean isPP95 = dir.hasEntry(PP95_DOCUMENT);
// PPT95 has 4 byte size, then data
if (!isPP95 && _contents.length >= 4) {
int size = LittleEndian.getInt(_contents);

+ 383
- 12
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFAutoShape.java View File

@@ -17,21 +17,122 @@

package org.apache.poi.hslf.usermodel;

import java.awt.geom.Arc2D;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Iterator;
import java.util.List;

import org.apache.poi.ddf.AbstractEscherOptRecord;
import org.apache.poi.ddf.EscherArrayProperty;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherProperties;
import org.apache.poi.sl.usermodel.*;
import org.apache.poi.ddf.EscherProperty;
import org.apache.poi.ddf.EscherSimpleProperty;
import org.apache.poi.sl.draw.binding.CTAdjPoint2D;
import org.apache.poi.sl.draw.binding.CTCustomGeometry2D;
import org.apache.poi.sl.draw.binding.CTPath2D;
import org.apache.poi.sl.draw.binding.CTPath2DArcTo;
import org.apache.poi.sl.draw.binding.CTPath2DCubicBezierTo;
import org.apache.poi.sl.draw.binding.CTPath2DLineTo;
import org.apache.poi.sl.draw.binding.CTPath2DList;
import org.apache.poi.sl.draw.binding.CTPath2DMoveTo;
import org.apache.poi.sl.draw.binding.ObjectFactory;
import org.apache.poi.sl.draw.geom.CustomGeometry;
import org.apache.poi.sl.usermodel.AutoShape;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.sl.usermodel.VerticalAlignment;
import org.apache.poi.ss.usermodel.ShapeTypes;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;

/**
* Represents an AutoShape.
* <p>
* Represents an AutoShape.<p>
*
* AutoShapes are drawing objects with a particular shape that may be customized through smart resizing and adjustments.
* See {@link ShapeTypes}
* </p>
*
* @author Yegor Kozlov
*/
public class HSLFAutoShape extends HSLFTextShape implements AutoShape<HSLFShape,HSLFTextParagraph> {
private static final POILogger LOG = POILogFactory.getLogger(HSLFAutoShape.class);

static final byte[] SEGMENTINFO_MOVETO = new byte[]{0x00, 0x40};
static final byte[] SEGMENTINFO_LINETO = new byte[]{0x00, (byte)0xAC};
static final byte[] SEGMENTINFO_ESCAPE = new byte[]{0x01, 0x00};
static final byte[] SEGMENTINFO_ESCAPE2 = new byte[]{0x01, 0x20};
static final byte[] SEGMENTINFO_CUBICTO = new byte[]{0x00, (byte)0xAD};
// OpenOffice inserts 0xB3 instead of 0xAD.
// protected static final byte[] SEGMENTINFO_CUBICTO2 = new byte[]{0x00, (byte)0xB3};
static final byte[] SEGMENTINFO_CLOSE = new byte[]{0x01, (byte)0x60};
static final byte[] SEGMENTINFO_END = new byte[]{0x00, (byte)0x80};

private static final BitField PATH_INFO = BitFieldFactory.getInstance(0xE000);
private static final BitField ESCAPE_INFO = BitFieldFactory.getInstance(0x1F00);

enum PathInfo {
lineTo(0),curveTo(1),moveTo(2),close(3),end(4),escape(5),clientEscape(6);
private final int flag;
PathInfo(int flag) {
this.flag = flag;
}
public int getFlag() {
return flag;
}
static PathInfo valueOf(int flag) {
for (PathInfo v : values()) {
if (v.flag == flag) {
return v;
}
}
return null;
}
}

enum EscapeInfo {
EXTENSION(0x0000),
ANGLE_ELLIPSE_TO(0x0001),
ANGLE_ELLIPSE(0x0002),
ARC_TO(0x0003),
ARC(0x0004),
CLOCKWISE_ARC_TO(0x0005),
CLOCKWISE_ARC(0x0006),
ELLIPTICAL_QUADRANT_X(0x0007),
ELLIPTICAL_QUADRANT_Y(0x0008),
QUADRATIC_BEZIER(0x0009),
NO_FILL(0X000A),
NO_LINE(0X000B),
AUTO_LINE(0X000C),
AUTO_CURVE(0X000D),
CORNER_LINE(0X000E),
CORNER_CURVE(0X000F),
SMOOTH_LINE(0X0010),
SMOOTH_CURVE(0X0011),
SYMMETRIC_LINE(0X0012),
SYMMETRIC_CURVE(0X0013),
FREEFORM(0X0014),
FILL_COLOR(0X0015),
LINE_COLOR(0X0016);

private final int flag;
EscapeInfo(int flag) {
this.flag = flag;
}
public int getFlag() {
return flag;
}
static EscapeInfo valueOf(int flag) {
for (EscapeInfo v : values()) {
if (v.flag == flag) {
return v;
}
}
return null;
}
}

protected HSLFAutoShape(EscherContainerRecord escherRecord, ShapeContainer<HSLFShape,HSLFTextParagraph> parent){
super(escherRecord, parent);
@@ -72,13 +173,11 @@ public class HSLFAutoShape extends HSLFTextShape implements AutoShape<HSLFShape,
}

/**
* Gets adjust value which controls smart resizing of the auto-shape.
* Gets adjust value which controls smart resizing of the auto-shape.<p>
*
* <p>
* The adjustment values are given in shape coordinates:
* the origin is at the top-left, positive-x is to the right, positive-y is down.
* The region from (0,0) to (S,S) maps to the geometry box of the shape (S=21600 is a constant).
* </p>
*
* @param idx the adjust index in the [0, 9] range
* @return the adjustment value
@@ -90,13 +189,11 @@ public class HSLFAutoShape extends HSLFTextShape implements AutoShape<HSLFShape,
}

/**
* Sets adjust value which controls smart resizing of the auto-shape.
* Sets adjust value which controls smart resizing of the auto-shape.<p>
*
* <p>
* The adjustment values are given in shape coordinates:
* the origin is at the top-left, positive-x is to the right, positive-y is down.
* The region from (0,0) to (S,S) maps to the geometry box of the shape (S=21600 is a constant).
* </p>
*
* @param idx the adjust index in the [0, 9] range
* @param val the adjustment value
@@ -106,4 +203,278 @@ public class HSLFAutoShape extends HSLFTextShape implements AutoShape<HSLFShape,

setEscherProperty((short)(EscherProperties.GEOMETRY__ADJUSTVALUE + idx), val);
}

@Override
public CustomGeometry getGeometry() {
return getGeometry(new Path2D.Double());
}

CustomGeometry getGeometry(Path2D path2D) {
final ObjectFactory of = new ObjectFactory();
final CTCustomGeometry2D cusGeo = of.createCTCustomGeometry2D();
cusGeo.setAvLst(of.createCTGeomGuideList());
cusGeo.setGdLst(of.createCTGeomGuideList());
cusGeo.setAhLst(of.createCTAdjustHandleList());
cusGeo.setCxnLst(of.createCTConnectionSiteList());

final AbstractEscherOptRecord opt = getEscherOptRecord();

EscherArrayProperty verticesProp = getShapeProp(opt, EscherProperties.GEOMETRY__VERTICES);
EscherArrayProperty segmentsProp = getShapeProp(opt, EscherProperties.GEOMETRY__SEGMENTINFO);

// return empty path if either GEOMETRY__VERTICES or GEOMETRY__SEGMENTINFO is missing, see Bugzilla 54188

//sanity check
if(verticesProp == null) {
LOG.log(POILogger.WARN, "Freeform is missing GEOMETRY__VERTICES ");
return super.getGeometry();
}
if(segmentsProp == null) {
LOG.log(POILogger.WARN, "Freeform is missing GEOMETRY__SEGMENTINFO ");
return super.getGeometry();
}

final Iterator<byte[]> vertIter = verticesProp.iterator();
final Iterator<byte[]> segIter = segmentsProp.iterator();
final int[] xyPoints = new int[2];
boolean isClosed = false;

final CTPath2DList pathLst = of.createCTPath2DList();
final CTPath2D pathCT = of.createCTPath2D();
final List<Object> moveLst = pathCT.getCloseOrMoveToOrLnTo();
pathLst.getPath().add(pathCT);
cusGeo.setPathLst(pathLst);

while (segIter.hasNext()) {
byte[] segElem = segIter.next();
HSLFFreeformShape.PathInfo pi = getPathInfo(segElem);
if (pi == null) {
continue;
}
switch (pi) {
case escape: {
handleEscapeInfo(pathCT, path2D, segElem, vertIter);
break;
}
case moveTo:
if (vertIter.hasNext()) {
final CTPath2DMoveTo m = of.createCTPath2DMoveTo();
m.setPt(fillPoint(vertIter.next(), xyPoints));
moveLst.add(m);
path2D.moveTo(xyPoints[0], xyPoints[1]);
}
break;
case lineTo:
if (vertIter.hasNext()) {
final CTPath2DLineTo m = of.createCTPath2DLineTo();
m.setPt(fillPoint(vertIter.next(), xyPoints));
moveLst.add(m);
path2D.lineTo(xyPoints[0], xyPoints[1]);
}
break;
case curveTo: {
final CTPath2DCubicBezierTo m = of.createCTPath2DCubicBezierTo();
List<CTAdjPoint2D> mLst = m.getPt();

int[] pts = new int[6];

for (int i=0; vertIter.hasNext() && i<3; i++) {
mLst.add(fillPoint(vertIter.next(), xyPoints));
pts[i*2] = xyPoints[0];
pts[i*2+1] = xyPoints[1];
if (i == 2) {
moveLst.add(m);
path2D.curveTo(pts[0], pts[1], pts[2], pts[3], pts[4], pts[5]);
}
}
break;
}
case close:
moveLst.add(of.createCTPath2DClose());
path2D.closePath();
isClosed = true;
break;
default:
break;
}
}

EscherSimpleProperty shapePath = getShapeProp(opt, EscherProperties.GEOMETRY__SHAPEPATH);
HSLFFreeformShape.ShapePath sp = HSLFFreeformShape.ShapePath.valueOf(shapePath == null ? 1 : shapePath.getPropertyValue());
if ((sp == HSLFFreeformShape.ShapePath.LINES_CLOSED || sp == HSLFFreeformShape.ShapePath.CURVES_CLOSED) && !isClosed) {
moveLst.add(of.createCTPath2DClose());
path2D.closePath();
}

EscherSimpleProperty geoLeft = getShapeProp(opt, EscherProperties.GEOMETRY__LEFT);
EscherSimpleProperty geoRight = getShapeProp(opt, EscherProperties.GEOMETRY__RIGHT);
EscherSimpleProperty geoTop = getShapeProp(opt, EscherProperties.GEOMETRY__TOP);
EscherSimpleProperty geoBottom = getShapeProp(opt, EscherProperties.GEOMETRY__BOTTOM);

final Rectangle2D bounds;
if (geoLeft != null && geoRight != null && geoTop != null && geoBottom != null) {
bounds = new Rectangle2D.Double();
bounds.setFrameFromDiagonal(
new Point2D.Double(geoLeft.getPropertyValue(), geoTop.getPropertyValue()),
new Point2D.Double(geoRight.getPropertyValue(), geoBottom.getPropertyValue())
);
} else {
bounds = path2D.getBounds2D();
}

pathCT.setW((int)Math.rint(bounds.getWidth()));
pathCT.setH((int)Math.rint(bounds.getHeight()));

return new CustomGeometry(cusGeo);
}

private void handleEscapeInfo(CTPath2D pathCT, Path2D path2D, byte[] segElem, Iterator<byte[]> vertIter) {
final ObjectFactory of = new ObjectFactory();
HSLFFreeformShape.EscapeInfo ei = getEscapeInfo(segElem);
switch (ei) {
case EXTENSION:
break;
case ANGLE_ELLIPSE_TO:
break;
case ANGLE_ELLIPSE:
break;
case ARC_TO: {
// The first two POINT values specify the bounding rectangle of the ellipse.
// The second two POINT values specify the radial vectors for the ellipse.
// The radial vectors are cast from the center of the bounding rectangle.
// The path starts at the POINT where the first radial vector intersects the
// bounding rectangle and goes to the POINT where the second radial vector
// intersects the bounding rectangle. The drawing direction is always counterclockwise.
// If the path has already been started, a line is drawn from the last POINT to
// the starting POINT of the arc; otherwise, a new path is started.
// The number of arc segments drawn equals the number of segments divided by four.

int[] r1 = new int[2], r2 = new int[2], start = new int[2], end = new int[2];
fillPoint(vertIter.next(), r1);
fillPoint(vertIter.next(), r2);
fillPoint(vertIter.next(), start);
fillPoint(vertIter.next(), end);

Arc2D arc2D = new Arc2D.Double();
Rectangle2D.Double bounds = new Rectangle2D.Double();
bounds.setFrameFromDiagonal(xy2p(r1), xy2p(r2));
arc2D.setFrame(bounds);
arc2D.setAngles(xy2p(start), xy2p(end));
path2D.append(arc2D, true);


CTPath2DArcTo arcTo = of.createCTPath2DArcTo();
arcTo.setHR(d2s(bounds.getHeight()/2.0));
arcTo.setWR(d2s(bounds.getWidth()/2.0));

arcTo.setStAng(d2s(-arc2D.getAngleStart()*60000.));
arcTo.setSwAng(d2s(-arc2D.getAngleExtent()*60000.));

pathCT.getCloseOrMoveToOrLnTo().add(arcTo);

break;
}
case ARC:
break;
case CLOCKWISE_ARC_TO:
break;
case CLOCKWISE_ARC:
break;
case ELLIPTICAL_QUADRANT_X:
break;
case ELLIPTICAL_QUADRANT_Y:
break;
case QUADRATIC_BEZIER:
break;
case NO_FILL:
break;
case NO_LINE:
break;
case AUTO_LINE:
break;
case AUTO_CURVE:
break;
case CORNER_LINE:
break;
case CORNER_CURVE:
break;
case SMOOTH_LINE:
break;
case SMOOTH_CURVE:
break;
case SYMMETRIC_LINE:
break;
case SYMMETRIC_CURVE:
break;
case FREEFORM:
break;
case FILL_COLOR:
break;
case LINE_COLOR:
break;
default:
break;
}
}

private static String d2s(double d) {
return Integer.toString((int)Math.rint(d));
}

private static Point2D xy2p(int[] xyPoints) {
return new Point2D.Double(xyPoints[0],xyPoints[1]);
}

private static HSLFFreeformShape.PathInfo getPathInfo(byte[] elem) {
int elemUS = LittleEndian.getUShort(elem, 0);
int pathInfo = PATH_INFO.getValue(elemUS);
return HSLFFreeformShape.PathInfo.valueOf(pathInfo);
}

private static HSLFFreeformShape.EscapeInfo getEscapeInfo(byte[] elem) {
int elemUS = LittleEndian.getUShort(elem, 0);
int escInfo = ESCAPE_INFO.getValue(elemUS);
return HSLFFreeformShape.EscapeInfo.valueOf(escInfo);
}


private static <T extends EscherProperty> T getShapeProp(AbstractEscherOptRecord opt, int propId) {
T prop = getEscherProperty(opt, (short)(propId + 0x4000));
if (prop == null) {
prop = getEscherProperty(opt, propId);
}
return prop;
}

private CTAdjPoint2D fillPoint(byte[] xyMaster, int[] xyPoints) {
if (xyMaster == null || xyPoints == null) {
LOG.log(POILogger.WARN, "Master bytes or points not set - ignore point");
return null;
}
if ((xyMaster.length != 4 && xyMaster.length != 8) || xyPoints.length != 2) {
LOG.log(POILogger.WARN, "Invalid number of master bytes for a single point - ignore point");
return null;
}

int x, y;
if (xyMaster.length == 4) {
x = LittleEndian.getShort(xyMaster, 0);
y = LittleEndian.getShort(xyMaster, 2);
} else {
x = LittleEndian.getInt(xyMaster, 0);
y = LittleEndian.getInt(xyMaster, 4);
}

xyPoints[0] = x;
xyPoints[1] = y;

return toPoint(xyPoints);
}

private static CTAdjPoint2D toPoint(int[] xyPoints) {
CTAdjPoint2D pt = new CTAdjPoint2D();
pt.setX(Integer.toString(xyPoints[0]));
pt.setY(Integer.toString(xyPoints[1]));
return pt;
}
}

+ 24
- 25
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFill.java View File

@@ -49,60 +49,61 @@ import org.apache.poi.util.Units;
/**
* Represents functionality provided by the 'Fill Effects' dialog in PowerPoint.
*/
@SuppressWarnings("WeakerAccess")
public final class HSLFFill {
private static final POILogger LOG = POILogFactory.getLogger(HSLFFill.class);

/**
* Fill with a solid color
*/
public static final int FILL_SOLID = 0;
static final int FILL_SOLID = 0;

/**
* Fill with a pattern (bitmap)
*/
public static final int FILL_PATTERN = 1;
static final int FILL_PATTERN = 1;

/**
* A texture (pattern with its own color map)
*/
public static final int FILL_TEXTURE = 2;
static final int FILL_TEXTURE = 2;

/**
* Center a picture in the shape
*/
public static final int FILL_PICTURE = 3;
static final int FILL_PICTURE = 3;

/**
* Shade from start to end points
*/
public static final int FILL_SHADE = 4;
static final int FILL_SHADE = 4;

/**
* Shade from bounding rectangle to end point
*/
public static final int FILL_SHADE_CENTER = 5;
static final int FILL_SHADE_CENTER = 5;

/**
* Shade from shape outline to end point
*/
public static final int FILL_SHADE_SHAPE = 6;
static final int FILL_SHADE_SHAPE = 6;

/**
* Similar to FILL_SHADE, but the fill angle
* is additionally scaled by the aspect ratio of
* the shape. If shape is square, it is the same as FILL_SHADE
*/
public static final int FILL_SHADE_SCALE = 7;
static final int FILL_SHADE_SCALE = 7;

/**
* shade to title
*/
public static final int FILL_SHADE_TITLE = 8;
static final int FILL_SHADE_TITLE = 8;

/**
* Use the background fill color/pattern
*/
public static final int FILL_BACKGROUND = 9;
static final int FILL_BACKGROUND = 9;

/**
* A bit that specifies whether the RecolorFillAsPicture bit is set.
@@ -214,7 +215,7 @@ public final class HSLFFill {
private HSLFShape shape;

/**
* Construct a <code>Fill</code> object for a shape.
* Construct a {@code Fill} object for a shape.
* Fill information will be read from shape's escher properties.
*
* @param shape the shape this background applies to
@@ -279,7 +280,7 @@ public final class HSLFFill {
@Override
public ColorStyle[] getGradientColors() {
ColorStyle cs[];
ColorStyle[] cs;
if (colorCnt == 0) {
cs = new ColorStyle[2];
cs[0] = wrapColor(getBackgroundColor());
@@ -288,7 +289,7 @@ public final class HSLFFill {
cs = new ColorStyle[colorCnt];
int idx = 0;
// TODO: handle palette colors and alpha(?) value
for (byte data[] : ep) {
for (byte[] data : ep) {
EscherColorRef ecr = new EscherColorRef(data, 0, 4);
cs[idx++] = wrapColor(shape.getColor(ecr));
}
@@ -302,13 +303,13 @@ public final class HSLFFill {
@Override
public float[] getGradientFractions() {
float frc[];
float[] frc;
if (colorCnt == 0) {
frc = new float[]{0, 1};
} else {
frc = new float[colorCnt];
int idx = 0;
for (byte data[] : ep) {
for (byte[] data : ep) {
double pos = Units.fixedPointToDouble(LittleEndian.getInt(data, 4));
frc[idx++] = (float)pos;
}
@@ -354,7 +355,7 @@ public final class HSLFFill {

/**
* Returns fill type.
* Must be one of the <code>FILL_*</code> constants defined in this class.
* Must be one of the {@code FILL_*} constants defined in this class.
*
* @return type of fill
*/
@@ -364,9 +365,7 @@ public final class HSLFFill {
return prop == null ? FILL_SOLID : prop.getPropertyValue();
}

/**
*/
protected void afterInsert(HSLFSheet sh){
void afterInsert(HSLFSheet sh){
AbstractEscherOptRecord opt = shape.getEscherOptRecord();
EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__PATTERNTEXTURE);
if(p != null) {
@@ -379,7 +378,7 @@ public final class HSLFFill {
}

@SuppressWarnings("resource")
protected EscherBSERecord getEscherBSERecord(int idx){
EscherBSERecord getEscherBSERecord(int idx){
HSLFSheet sheet = shape.getSheet();
if(sheet == null) {
LOG.log(POILogger.DEBUG, "Fill has not yet been assigned to a sheet");
@@ -399,7 +398,7 @@ public final class HSLFFill {

/**
* Sets fill type.
* Must be one of the <code>FILL_*</code> constants defined in this class.
* Must be one of the {@code FILL_*} constants defined in this class.
*
* @param type type of the fill
*/
@@ -415,10 +414,10 @@ public final class HSLFFill {
AbstractEscherOptRecord opt = shape.getEscherOptRecord();
EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__NOFILLHITTEST);
int propVal = (p == null) ? 0 : p.getPropertyValue();
return (FILL_USE_FILLED.isSet(propVal) && !FILL_FILLED.isSet(propVal))
? null
: shape.getColor(EscherProperties.FILL__FILLCOLOR, EscherProperties.FILL__FILLOPACITY, -1);
: shape.getColor(EscherProperties.FILL__FILLCOLOR, EscherProperties.FILL__FILLOPACITY);
}

/**
@@ -462,7 +461,7 @@ public final class HSLFFill {

return (FILL_USE_FILLED.isSet(propVal) && !FILL_FILLED.isSet(propVal))
? null
: shape.getColor(EscherProperties.FILL__FILLBACKCOLOR, EscherProperties.FILL__FILLOPACITY, -1);
: shape.getColor(EscherProperties.FILL__FILLBACKCOLOR, EscherProperties.FILL__FILLOPACITY);
}

/**
@@ -480,7 +479,7 @@ public final class HSLFFill {
}

/**
* <code>PictureData</code> object used in a texture, pattern of picture fill.
* {@code PictureData} object used in a texture, pattern of picture fill.
*/
@SuppressWarnings("resource")
public HSLFPictureData getPictureData(){

+ 12
- 252
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFFreeformShape.java View File

@@ -23,20 +23,16 @@ import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.poi.ddf.AbstractEscherOptRecord;
import org.apache.poi.ddf.EscherArrayProperty;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherProperties;
import org.apache.poi.ddf.EscherProperty;
import org.apache.poi.ddf.EscherSimpleProperty;
import org.apache.poi.sl.usermodel.FreeformShape;
import org.apache.poi.sl.usermodel.ShapeContainer;
import org.apache.poi.sl.usermodel.ShapeType;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
@@ -53,79 +49,6 @@ import org.apache.poi.util.Units;
public final class HSLFFreeformShape extends HSLFAutoShape implements FreeformShape<HSLFShape,HSLFTextParagraph> {
private static final POILogger LOG = POILogFactory.getLogger(HSLFFreeformShape.class);

private static final byte[] SEGMENTINFO_MOVETO = new byte[]{0x00, 0x40};
private static final byte[] SEGMENTINFO_LINETO = new byte[]{0x00, (byte)0xAC};
private static final byte[] SEGMENTINFO_ESCAPE = new byte[]{0x01, 0x00};
private static final byte[] SEGMENTINFO_ESCAPE2 = new byte[]{0x01, 0x20};
private static final byte[] SEGMENTINFO_CUBICTO = new byte[]{0x00, (byte)0xAD};
// OpenOffice inserts 0xB3 instead of 0xAD.
// private static final byte[] SEGMENTINFO_CUBICTO2 = new byte[]{0x00, (byte)0xB3};
private static final byte[] SEGMENTINFO_CLOSE = new byte[]{0x01, (byte)0x60};
private static final byte[] SEGMENTINFO_END = new byte[]{0x00, (byte)0x80};

private static final BitField PATH_INFO = BitFieldFactory.getInstance(0xE000);
// private static final BitField ESCAPE_INFO = BitFieldFactory.getInstance(0x1F00);

enum PathInfo {
lineTo(0),curveTo(1),moveTo(2),close(3),end(4),escape(5),clientEscape(6);
private final int flag;
PathInfo(int flag) {
this.flag = flag;
}
public int getFlag() {
return flag;
}
static PathInfo valueOf(int flag) {
for (PathInfo v : values()) {
if (v.flag == flag) {
return v;
}
}
return null;
}
}

enum EscapeInfo {
EXTENSION(0x0000),
ANGLE_ELLIPSE_TO(0x0001),
ANGLE_ELLIPSE(0x0002),
ARC_TO(0x0003),
ARC(0x0004),
CLOCKWISE_ARC_TO(0x0005),
CLOCKWISE_ARC(0x0006),
ELLIPTICAL_QUADRANT_X(0x0007),
ELLIPTICAL_QUADRANT_Y(0x0008),
QUADRATIC_BEZIER(0x0009),
NO_FILL(0X000A),
NO_LINE(0X000B),
AUTO_LINE(0X000C),
AUTO_CURVE(0X000D),
CORNER_LINE(0X000E),
CORNER_CURVE(0X000F),
SMOOTH_LINE(0X0010),
SMOOTH_CURVE(0X0011),
SYMMETRIC_LINE(0X0012),
SYMMETRIC_CURVE(0X0013),
FREEFORM(0X0014),
FILL_COLOR(0X0015),
LINE_COLOR(0X0016);

private final int flag;
EscapeInfo(int flag) {
this.flag = flag;
}
public int getFlag() {
return flag;
}
static EscapeInfo valueOf(int flag) {
for (EscapeInfo v : values()) {
if (v.flag == flag) {
return v;
}
}
return null;
}
}

enum ShapePath {
LINES(0),
@@ -182,9 +105,9 @@ public final class HSLFFreeformShape extends HSLFAutoShape implements FreeformSh
}

@Override
public int setPath(Path2D.Double path) {
public int setPath(Path2D path) {
Rectangle2D bounds = path.getBounds2D();
PathIterator it = path.getPathIterator(new AffineTransform());
PathIterator it = path.getPathIterator(null);

List<byte[]> segInfo = new ArrayList<>();
List<Point2D.Double> pntInfo = new ArrayList<>();
@@ -275,187 +198,24 @@ public final class HSLFFreeformShape extends HSLFAutoShape implements FreeformSh
}

@Override
public Path2D.Double getPath(){
AbstractEscherOptRecord opt = getEscherOptRecord();

EscherArrayProperty verticesProp = getShapeProp(opt, EscherProperties.GEOMETRY__VERTICES);
EscherArrayProperty segmentsProp = getShapeProp(opt, EscherProperties.GEOMETRY__SEGMENTINFO);

// return empty path if either GEOMETRY__VERTICES or GEOMETRY__SEGMENTINFO is missing, see Bugzilla 54188
Path2D.Double path = new Path2D.Double();
public Path2D getPath(){
Path2D path2D = new Path2D.Double();
getGeometry(path2D);

//sanity check
if(verticesProp == null) {
LOG.log(POILogger.WARN, "Freeform is missing GEOMETRY__VERTICES ");
return path;
}
if(segmentsProp == null) {
LOG.log(POILogger.WARN, "Freeform is missing GEOMETRY__SEGMENTINFO ");
return path;
}

Iterator<byte[]> vertIter = verticesProp.iterator();
Iterator<byte[]> segIter = segmentsProp.iterator();
double xyPoints[] = new double[2];
while (vertIter.hasNext() && segIter.hasNext()) {
byte[] segElem = segIter.next();
PathInfo pi = getPathInfo(segElem);
if (pi != null) {
switch (pi) {
case escape: {
// handleEscapeInfo(path, segElem, vertIter);
break;
}
case moveTo: {
fillPoint(vertIter.next(), xyPoints);
double x = xyPoints[0];
double y = xyPoints[1];
path.moveTo(x, y);
break;
}
case curveTo: {
fillPoint(vertIter.next(), xyPoints);
double x1 = xyPoints[0];
double y1 = xyPoints[1];
fillPoint(vertIter.next(), xyPoints);
double x2 = xyPoints[0];
double y2 = xyPoints[1];
fillPoint(vertIter.next(), xyPoints);
double x3 = xyPoints[0];
double y3 = xyPoints[1];
path.curveTo(x1, y1, x2, y2, x3, y3);
break;
}
case lineTo:
if (vertIter.hasNext()) {
fillPoint(vertIter.next(), xyPoints);
double x = xyPoints[0];
double y = xyPoints[1];
path.lineTo(x, y);
}
break;
case close:
path.closePath();
break;
default:
break;
}
}
}

EscherSimpleProperty shapePath = getShapeProp(opt, EscherProperties.GEOMETRY__SHAPEPATH);
ShapePath sp = ShapePath.valueOf(shapePath == null ? 1 : shapePath.getPropertyValue());
if (sp == ShapePath.LINES_CLOSED || sp == ShapePath.CURVES_CLOSED) {
path.closePath();
}
Rectangle2D bounds = path2D.getBounds2D();
Rectangle2D anchor = getAnchor();
Rectangle2D bounds = path.getBounds2D();
AffineTransform at = new AffineTransform();
at.translate(anchor.getX(), anchor.getY());
at.scale(
anchor.getWidth()/bounds.getWidth(),
anchor.getHeight()/bounds.getHeight()
);
return new Path2D.Double(at.createTransformedShape(path));
}
private void fillPoint(byte xyMaster[], double xyPoints[]) {
if (xyMaster == null || xyPoints == null) {
LOG.log(POILogger.WARN, "Master bytes or points not set - ignore point");
return;
}
if ((xyMaster.length != 4 && xyMaster.length != 8) || xyPoints.length != 2) {
LOG.log(POILogger.WARN, "Invalid number of master bytes for a single point - ignore point");
return;
}
int x, y;
if (xyMaster.length == 4) {
x = LittleEndian.getShort(xyMaster, 0);
y = LittleEndian.getShort(xyMaster, 2);
} else {
x = LittleEndian.getInt(xyMaster, 0);
y = LittleEndian.getInt(xyMaster, 4);
}
xyPoints[0] = Units.masterToPoints(x);
xyPoints[1] = Units.masterToPoints(y);
}
private static <T extends EscherProperty> T getShapeProp(AbstractEscherOptRecord opt, int propId) {
T prop = getEscherProperty(opt, (short)(propId + 0x4000));
if (prop == null) {
prop = getEscherProperty(opt, propId);
}
return prop;
}
// private void handleEscapeInfo(Path2D path, byte segElem[], Iterator<byte[]> vertIter) {
// EscapeInfo ei = getEscapeInfo(segElem);
// switch (ei) {
// case EXTENSION:
// break;
// case ANGLE_ELLIPSE_TO:
// break;
// case ANGLE_ELLIPSE:
// break;
// case ARC_TO:
// break;
// case ARC:
// break;
// case CLOCKWISE_ARC_TO:
// break;
// case CLOCKWISE_ARC:
// break;
// case ELLIPTICAL_QUADRANT_X:
// break;
// case ELLIPTICAL_QUADRANT_Y:
// break;
// case QUADRATIC_BEZIER:
// break;
// case NO_FILL:
// break;
// case NO_LINE:
// break;
// case AUTO_LINE:
// break;
// case AUTO_CURVE:
// break;
// case CORNER_LINE:
// break;
// case CORNER_CURVE:
// break;
// case SMOOTH_LINE:
// break;
// case SMOOTH_CURVE:
// break;
// case SYMMETRIC_LINE:
// break;
// case SYMMETRIC_CURVE:
// break;
// case FREEFORM:
// break;
// case FILL_COLOR:
// break;
// case LINE_COLOR:
// break;
// default:
// break;
// }
// }

private static PathInfo getPathInfo(byte elem[]) {
int elemUS = LittleEndian.getUShort(elem, 0);
int pathInfo = PATH_INFO.getValue(elemUS);
return PathInfo.valueOf(pathInfo);
path2D.transform(at);


return path2D;
}
// private static EscapeInfo getEscapeInfo(byte elem[]) {
// int elemUS = LittleEndian.getUShort(elem, 0);
// int escInfo = ESCAPE_INFO.getValue(elemUS);
// return EscapeInfo.valueOf(escInfo);
// }


}

+ 12
- 11
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFShape.java View File

@@ -358,17 +358,18 @@ public abstract class HSLFShape implements Shape<HSLFShape,HSLFTextParagraph> {
_sheet = sheet;
}

Color getColor(short colorProperty, short opacityProperty, int defaultColor){
AbstractEscherOptRecord opt = getEscherOptRecord();
EscherSimpleProperty p = getEscherProperty(opt, colorProperty);
if(p == null && defaultColor == -1) return null;

int val = (p == null) ? defaultColor : p.getPropertyValue();

EscherColorRef ecr = new EscherColorRef(val);
Color col = getColor(ecr);
if (col == null) {
return null;
Color getColor(short colorProperty, short opacityProperty){
final AbstractEscherOptRecord opt = getEscherOptRecord();
final EscherSimpleProperty colProp = getEscherProperty(opt, colorProperty);
final Color col;
if (colProp == null) {
col = Color.WHITE;
} else {
EscherColorRef ecr = new EscherColorRef(colProp.getPropertyValue());
col = getColor(ecr);
if (col == null) {
return null;
}
}

double alpha = getAlpha(opacityProperty);

+ 3
- 3
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSimpleShape.java View File

@@ -164,7 +164,7 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
return null;
}

Color clr = getColor(EscherProperties.LINESTYLE__COLOR, EscherProperties.LINESTYLE__OPACITY, -1);
Color clr = getColor(EscherProperties.LINESTYLE__COLOR, EscherProperties.LINESTYLE__OPACITY);
return clr == null ? null : clr;
}

@@ -179,7 +179,7 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
return null;
}

Color clr = getColor(EscherProperties.LINESTYLE__BACKCOLOR, EscherProperties.LINESTYLE__OPACITY, -1);
Color clr = getColor(EscherProperties.LINESTYLE__BACKCOLOR, EscherProperties.LINESTYLE__OPACITY);
return clr == null ? null : clr;
}

@@ -385,7 +385,7 @@ public abstract class HSLFSimpleShape extends HSLFShape implements SimpleShape<H
* @return color of the line. If color is not set returns <code>java.awt.Color.black</code>
*/
public Color getShadowColor(){
Color clr = getColor(EscherProperties.SHADOWSTYLE__COLOR, EscherProperties.SHADOWSTYLE__OPACITY, -1);
Color clr = getColor(EscherProperties.SHADOWSTYLE__COLOR, EscherProperties.SHADOWSTYLE__OPACITY);
return clr == null ? Color.black : clr;
}


+ 1
- 0
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShow.java View File

@@ -71,6 +71,7 @@ public final class HSLFSlideShow implements SlideShow<HSLFShape,HSLFTextParagrap

/** Powerpoint document entry/stream name */
public static final String POWERPOINT_DOCUMENT = "PowerPoint Document";
public static final String PP95_DOCUMENT = "PP40";

enum LoadSavePhase {
INIT, LOADED

+ 14
- 5
src/scratchpad/src/org/apache/poi/hslf/usermodel/HSLFSlideShowImpl.java View File

@@ -17,6 +17,9 @@

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.ByteArrayOutputStream;
import java.io.Closeable;
@@ -35,6 +38,7 @@ import java.util.TreeMap;
import org.apache.poi.POIDocument;
import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException;
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.DocumentEncryptionAtom;
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
*/
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
DocumentEntry docProps =
(DocumentEntry) getDirectory().getEntry(HSLFSlideShow.POWERPOINT_DOCUMENT);
DocumentEntry docProps = (DocumentEntry)dir.getEntry(POWERPOINT_DOCUMENT);

// Grab the document stream
int len = docProps.getSize();
try (InputStream is = getDirectory().createDocumentInputStream(HSLFSlideShow.POWERPOINT_DOCUMENT)) {
try (InputStream is = dir.createDocumentInputStream(docProps)) {
_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
ByteArrayInputStream bais = new ByteArrayInputStream(_docstream);
outFS.createOrUpdateDocument(bais, HSLFSlideShow.POWERPOINT_DOCUMENT);
writtenEntries.add(HSLFSlideShow.POWERPOINT_DOCUMENT);
outFS.createOrUpdateDocument(bais, POWERPOINT_DOCUMENT);
writtenEntries.add(POWERPOINT_DOCUMENT);

currentUser.setEncrypted(encryptedSS.getDocumentEncryptionAtom() != null);
currentUser.writeToFS(outFS);

+ 0
- 1
src/scratchpad/testcases/org/apache/poi/hslf/model/AllHSLFModelTests.java View File

@@ -25,7 +25,6 @@ import org.junit.runners.Suite;
*/
@RunWith(Suite.class)
@Suite.SuiteClasses({
TestBackground.class,
TestFreeform.class,
TestHeadersFooters.class,
TestHyperlink.class,

+ 1
- 1
src/scratchpad/testcases/org/apache/poi/hslf/model/TestFreeform.java View File

@@ -87,7 +87,7 @@ public final class TestFreeform {
public void test54188() {

HSLFFreeformShape p = new HSLFFreeformShape();
Path2D.Double path = p.getPath();
Path2D path = p.getPath();
Path2D.Double emptyPath = new Path2D.Double();
assertEquals(emptyPath.getBounds2D(), path.getBounds2D());
}

+ 1
- 0
src/scratchpad/testcases/org/apache/poi/hslf/usermodel/AllHSLFUserModelTests.java View File

@@ -26,6 +26,7 @@ import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
TestAddingSlides.class,
TestBackground.class,
TestBugs.class,
TestCounts.class,
TestMostRecentRecords.class,

src/scratchpad/testcases/org/apache/poi/hslf/model/TestBackground.java → src/scratchpad/testcases/org/apache/poi/hslf/usermodel/TestBackground.java View File

@@ -15,7 +15,7 @@
limitations under the License.
==================================================================== */

package org.apache.poi.hslf.model;
package org.apache.poi.hslf.usermodel;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

+ 81
- 0
src/testcases/org/apache/poi/poifs/filesystem/TestFileMagic.java 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));
}
}
}

+ 15
- 0
src/testcases/org/apache/poi/poifs/filesystem/TestPOIFSFileSystem.java View File

@@ -17,6 +17,7 @@

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.assertTrue;
import static org.junit.Assert.fail;
@@ -278,4 +279,18 @@ public final class TestPOIFSFileSystem {
private static InputStream openSampleStream(String 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)));
}
}

+ 66
- 0
src/testcases/org/apache/poi/ss/formula/SheetRangeAndWorkbookIndexFormatterTest.java 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);
}
}

+ 2
- 2
src/testcases/org/apache/poi/ss/usermodel/TestExcelStyleDateFormatter.java View File

@@ -91,9 +91,9 @@ public class TestExcelStyleDateFormatter {
*/
private int localeIndex(Locale locale) {
final String provider = System.getProperty("java.locale.providers");
return jreVersion < 12 ||
return jreVersion < 9 ||
!locale.equals (Locale.CHINESE) ||
(provider != null && provider.startsWith("JRE"))
(provider != null && (provider.startsWith("JRE") || provider.startsWith("COMPAT")))
? 0 : 1;
}


BIN
test-data/document/60316.docx View File


BIN
test-data/document/60316b.dotx View File


BIN
test-data/slideshow/customGeo.ppt View File


BIN
test-data/slideshow/customGeo.pptx View File


BIN
test-data/slideshow/keyframes.pptx View File


BIN
test-data/slideshow/pp40only.ppt View File


Loading…
Cancel
Save