<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
<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}"/>
</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}"/>
<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">
<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}"/>
<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>
</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>
<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>
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>
<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>
<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"/>
<include name="org/apache/poi/**"/>
</packageset>
- <arg value="${javadoc9addmods}"/>
+ <arg value="${javadoc9addmods}" if:set="${javadoc9addmods}"/>
<doctitle><![CDATA[<h1>POI API Documentation</h1>]]></doctitle>
<bottom>
sonar/*/src/**,
compile-lib/**,
ooxml-lib/**,
+ ooxml-testlib/**,
scripts/**,
TEST*,
*.ipr,
</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" />
<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>
<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>
--- /dev/null
+/*
+ * ====================================================================
+ * 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);
+ }
+}
+
--- /dev/null
+/*
+ * ====================================================================
+ * 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);
+ }
+}
+
"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",
import java.util.Locale;
import java.util.Set;
-import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import org.apache.poi.EncryptedDocumentException;
}
private void exportToXML(XSSFWorkbook wb) throws SAXException,
- ParserConfigurationException, TransformerException {
+ TransformerException {
for (XSSFMap map : wb.getCustomXMLMappings()) {
XSSFExportToXml exporter = new XSSFExportToXml(map);
// 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
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 {
*
* @author Glen Stampoultzis (glens at apache.org)
*/
+@SuppressWarnings("WeakerAccess")
public final class EscherProperties {
// Property constants
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;
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");
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");
}
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();
}
}
* 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>
*
* 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> {
@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);
}
/**
* Only for internal calls - code based on this is not supported ...
+ *
+ * @return The list of records.
*/
@Internal
public WorkbookRecordList getWorkbookRecordList() {
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 {
_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()
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());
}
* <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
* 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>
* 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
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");
}
/**
+ * 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) {
/**
* 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);
&& 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) {
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;
* @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) {
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
/** 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 */
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;
}
}
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>
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;
if(fill != null) {
graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, anchor);
graphics.setPaint(fill);
- graphics.fill(anchor2);
+ fillPaintWorkaround(graphics, anchor2);
}
}
-
+
protected Background<?,?> getShape() {
return (Background<?,?>)shape;
}
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;
- }
}
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;
@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);
}
};
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());
* @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;
}
*
* 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;
* 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;
}
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);
}
/**
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);
+ }
+ }
}
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;
graphics.setPaint(fillMod);
java.awt.Shape s = o.getOutline();
graphics.setRenderingHint(Drawable.GRADIENT_SHAPE, s);
- graphics.fill(s);
+ fillPaintWorkaround(graphics, s);
}
}
}
graphics.setPaint(shadowColor);
if(fill != null && p.isFilled()){
- graphics.fill(s);
+ fillPaintWorkaround(graphics, s);
} else if (line != null && p.isStroked()) {
graphics.draw(s);
}
}
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;
}
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;
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) {
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;
}
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) {
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);
- 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);
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);
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;
}
}
- 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){
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;
};
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();
+ }
}
/**
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
* @param path shape outline
* @return the number of points written
*/
- int setPath(Path2D.Double path);
+ int setPath(Path2D path);
}
* @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) {
/**
* @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) {
}
}
- 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);
}
}
- 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");
--- /dev/null
+/* ====================================================================
+ 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;
+ }
+}
i = 0;
j++;
}
- matrix[j][i++] = aVector;
+ if (j < matrix.length) matrix[j][i++] = aVector;
}
}
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;
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();
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;
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();
* 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) {
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 = "?";
points /= MASTER_DPI;
return points;
}
-
+
public static int pointsToMaster(double points) {
points *= MASTER_DPI;
points /= POINT_DPI;
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.");
/**
* 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");
+ }
+ }
+ }
}
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";
}
"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.
/**
* 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.
*/
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
+import java.security.Security;
import java.security.Signature;
import java.security.SignatureException;
@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);
}
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;
@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
*/
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
*
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);
}
* 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.
*/
* Return all the charts in the slideshow
*/
public List<XSLFChart> getCharts() {
- return _charts;
+ return Collections.unmodifiableList(_charts);
}
/**
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
@Beta
public final class XSLFChart extends XDDFChart {
+ private static String CHART_URI = "http://schemas.openxmlformats.org/drawingml/2006/chart";
+
/**
* Construct a PresentationML chart.
*/
};
}
}
+
+ /**
+ * 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;
+ }
}
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));
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;
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;
}
@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();
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() {
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;
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;
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;
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);
+ }
+
}
}
/**
- *
* @return definition of the shape geometry
*/
@Override
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;
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;
*/
private final SharedStringsTable _sharedStringSource;
+ private Zip64Mode zip64Mode = Zip64Mode.AsNeeded;
+
/**
* Construct a new workbook with default row window size
*/
}
}
}
+
/**
* Construct an empty workbook and specify the window for row access.
* <p>
_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.
*
public boolean isCompressTempFiles() {
return _compressTmpFiles;
}
+
/**
* Set whether temp files should be compressed.
* <p>
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()) {
/**
* 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;
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;
* @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);
}
/**
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;
XSSFWorkbook newWorkbook =
XSSFTestDataSamples.writeOutAndReadBack(workbook);
workbook.close();
- assertTrue(workbook != newWorkbook);
+ assertNotSame(workbook, newWorkbook);
POIXMLProperties newProps = newWorkbook.getProperties();
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();
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;
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();
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);
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);
}
@After
- public void closeResoures() throws IOException {
+ public void closeResources() throws IOException {
if(xml != null) {
xml.close();
}
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";
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;
* @author Yegor Kozlov
*/
public class TestXSLFSlide {
-
+
@Test
public void testReadShapes() throws IOException {
XMLSlideShow ppt = XSLFTestDataSamples.openSampleDocument("shapes.pptx");
XSLFTable tbl = (XSLFTable)shapes4.get(0);
assertEquals(3, tbl.getNumberOfColumns());
assertEquals(6, tbl.getNumberOfRows());
-
+
ppt.close();
}
assertFalse(slide.getFollowMasterGraphics());
slide.setFollowMasterGraphics(true);
assertTrue(slide.getFollowMasterGraphics());
-
+
ppt.close();
}
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();
}
}
}
assertEquals(30, ppt.getSlides().size());
-
+
ppt.close();
- }
-}
\ No newline at end of file
+ }
+
+ @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();
+ }
+}
* @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);
file = TempFile.createTempFile(testName, ".xlsx");
}
if (file.exists()) {
- file.delete();
+ if(!file.delete()) {
+ throw new IOException("Could not delete file " + file);
+ }
}
return file;
}
*
* @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);
* 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
*
* @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;
}
/**
*
* @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;
}
*
* @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();
- }
}
/**
*
* @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();
- }
}
/**
//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");
+ }
}
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;
// 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);
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);
}
/**
- * 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
}
/**
- * 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
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;
+ }
}
/**
* 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.
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
@Override
public ColorStyle[] getGradientColors() {
- ColorStyle cs[];
+ ColorStyle[] cs;
if (colorCnt == 0) {
cs = new ColorStyle[2];
cs[0] = wrapColor(getBackgroundColor());
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));
}
@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;
}
/**
* 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
*/
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) {
}
@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");
/**
* 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
*/
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);
}
/**
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);
}
/**
}
/**
- * <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(){
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;
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),
}
@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<>();
}
@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);
-// }
+
+
}
_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);
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;
}
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;
}
* @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;
}
/** Powerpoint document entry/stream name */
public static final String POWERPOINT_DOCUMENT = "PowerPoint Document";
+ public static final String PP95_DOCUMENT = "PP40";
enum LoadSavePhase {
INIT, LOADED
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;
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;
* @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);
}
}
// 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);
*/
@RunWith(Suite.class)
@Suite.SuiteClasses({
- TestBackground.class,
TestFreeform.class,
TestHeadersFooters.class,
TestHyperlink.class,
+++ /dev/null
-/* ====================================================================
- 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.hslf.model;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.awt.Color;
-import java.io.IOException;
-import java.util.List;
-
-import org.apache.poi.POIDataSamples;
-import org.apache.poi.ddf.AbstractEscherOptRecord;
-import org.apache.poi.ddf.EscherBSERecord;
-import org.apache.poi.ddf.EscherContainerRecord;
-import org.apache.poi.ddf.EscherProperties;
-import org.apache.poi.ddf.EscherRecord;
-import org.apache.poi.ddf.EscherSimpleProperty;
-import org.apache.poi.hslf.HSLFTestDataSamples;
-import org.apache.poi.hslf.record.Document;
-import org.apache.poi.hslf.usermodel.HSLFAutoShape;
-import org.apache.poi.hslf.usermodel.HSLFFill;
-import org.apache.poi.hslf.usermodel.HSLFPictureData;
-import org.apache.poi.hslf.usermodel.HSLFShape;
-import org.apache.poi.hslf.usermodel.HSLFSheet;
-import org.apache.poi.hslf.usermodel.HSLFSlide;
-import org.apache.poi.hslf.usermodel.HSLFSlideShow;
-import org.apache.poi.sl.usermodel.PictureData.PictureType;
-import org.apache.poi.sl.usermodel.ShapeType;
-import org.junit.Test;
-
-
-/**
- * Test <code>Fill</code> object.
- *
- * @author Yegor Kozlov
- */
-public final class TestBackground {
- private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
-
- /**
- * Default background for slide, shape and slide master.
- */
- @Test
- public void defaults() throws IOException {
- HSLFSlideShow ppt = new HSLFSlideShow();
-
- assertEquals(HSLFFill.FILL_SOLID, ppt.getSlideMasters().get(0).getBackground().getFill().getFillType());
-
- HSLFSlide slide = ppt.createSlide();
- assertTrue(slide.getFollowMasterBackground());
- assertEquals(HSLFFill.FILL_SOLID, slide.getBackground().getFill().getFillType());
-
- HSLFShape shape = new HSLFAutoShape(ShapeType.RECT);
- assertEquals(HSLFFill.FILL_SOLID, shape.getFill().getFillType());
- ppt.close();
- }
-
- /**
- * Read fill information from an reference ppt file
- */
- @Test
- public void readBackground() throws IOException {
- HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow("backgrounds.ppt");
- HSLFFill fill;
- HSLFShape shape;
-
- List<HSLFSlide> slide = ppt.getSlides();
-
- fill = slide.get(0).getBackground().getFill();
- assertEquals(HSLFFill.FILL_PICTURE, fill.getFillType());
- shape = slide.get(0).getShapes().get(0);
- assertEquals(HSLFFill.FILL_SOLID, shape.getFill().getFillType());
-
- fill = slide.get(1).getBackground().getFill();
- assertEquals(HSLFFill.FILL_PATTERN, fill.getFillType());
- shape = slide.get(1).getShapes().get(0);
- assertEquals(HSLFFill.FILL_BACKGROUND, shape.getFill().getFillType());
-
- fill = slide.get(2).getBackground().getFill();
- assertEquals(HSLFFill.FILL_TEXTURE, fill.getFillType());
- shape = slide.get(2).getShapes().get(0);
- assertEquals(HSLFFill.FILL_PICTURE, shape.getFill().getFillType());
-
- fill = slide.get(3).getBackground().getFill();
- assertEquals(HSLFFill.FILL_SHADE_CENTER, fill.getFillType());
- shape = slide.get(3).getShapes().get(0);
- assertEquals(HSLFFill.FILL_SHADE, shape.getFill().getFillType());
- ppt.close();
- }
-
- /**
- * Create a ppt with various fill effects
- */
- @Test
- public void backgroundPicture() throws IOException {
- HSLFSlideShow ppt1 = new HSLFSlideShow();
- HSLFSlide slide;
- HSLFFill fill;
- HSLFShape shape;
- HSLFPictureData data;
-
- //slide 1
- slide = ppt1.createSlide();
- slide.setFollowMasterBackground(false);
- fill = slide.getBackground().getFill();
- data = ppt1.addPicture(_slTests.readFile("tomcat.png"), PictureType.PNG);
- fill.setFillType(HSLFFill.FILL_PICTURE);
- fill.setPictureData(data);
-
- shape = new HSLFAutoShape(ShapeType.RECT);
- shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200));
- fill = shape.getFill();
- fill.setFillType(HSLFFill.FILL_SOLID);
- slide.addShape(shape);
-
- //slide 2
- slide = ppt1.createSlide();
- slide.setFollowMasterBackground(false);
- fill = slide.getBackground().getFill();
- data = ppt1.addPicture(_slTests.readFile("tomcat.png"), PictureType.PNG);
- fill.setFillType(HSLFFill.FILL_PATTERN);
- fill.setPictureData(data);
- fill.setBackgroundColor(Color.green);
- fill.setForegroundColor(Color.red);
-
- shape = new HSLFAutoShape(ShapeType.RECT);
- shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200));
- fill = shape.getFill();
- fill.setFillType(HSLFFill.FILL_BACKGROUND);
- slide.addShape(shape);
-
- //slide 3
- slide = ppt1.createSlide();
- slide.setFollowMasterBackground(false);
- fill = slide.getBackground().getFill();
- data = ppt1.addPicture(_slTests.readFile("tomcat.png"), PictureType.PNG);
- fill.setFillType(HSLFFill.FILL_TEXTURE);
- fill.setPictureData(data);
-
- shape = new HSLFAutoShape(ShapeType.RECT);
- shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200));
- fill = shape.getFill();
- fill.setFillType(HSLFFill.FILL_PICTURE);
- data = ppt1.addPicture(_slTests.readFile("clock.jpg"), PictureType.JPEG);
- fill.setPictureData(data);
- slide.addShape(shape);
-
- // slide 4
- slide = ppt1.createSlide();
- slide.setFollowMasterBackground(false);
- fill = slide.getBackground().getFill();
- fill.setFillType(HSLFFill.FILL_SHADE_CENTER);
- fill.setBackgroundColor(Color.white);
- fill.setForegroundColor(Color.darkGray);
-
- shape = new HSLFAutoShape(ShapeType.RECT);
- shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200));
- fill = shape.getFill();
- fill.setFillType(HSLFFill.FILL_SHADE);
- fill.setBackgroundColor(Color.red);
- fill.setForegroundColor(Color.green);
- slide.addShape(shape);
-
- //serialize and read again
- HSLFSlideShow ppt2 = HSLFTestDataSamples.writeOutAndReadBack(ppt1);
- List<HSLFSlide> slides = ppt2.getSlides();
-
- fill = slides.get(0).getBackground().getFill();
- assertEquals(HSLFFill.FILL_PICTURE, fill.getFillType());
- assertEquals(3, getFillPictureRefCount(slides.get(0).getBackground(), fill));
- shape = slides.get(0).getShapes().get(0);
- assertEquals(HSLFFill.FILL_SOLID, shape.getFill().getFillType());
-
- fill = slides.get(1).getBackground().getFill();
- assertEquals(HSLFFill.FILL_PATTERN, fill.getFillType());
- shape = slides.get(1).getShapes().get(0);
- assertEquals(HSLFFill.FILL_BACKGROUND, shape.getFill().getFillType());
-
- fill = slides.get(2).getBackground().getFill();
- assertEquals(HSLFFill.FILL_TEXTURE, fill.getFillType());
- assertEquals(3, getFillPictureRefCount(slides.get(2).getBackground(), fill));
- shape = slides.get(2).getShapes().get(0);
- assertEquals(HSLFFill.FILL_PICTURE, shape.getFill().getFillType());
- assertEquals(1, getFillPictureRefCount(shape, fill));
-
- fill = slides.get(3).getBackground().getFill();
- assertEquals(HSLFFill.FILL_SHADE_CENTER, fill.getFillType());
- shape = slides.get(3).getShapes().get(0);
- assertEquals(HSLFFill.FILL_SHADE, shape.getFill().getFillType());
- ppt2.close();
- ppt1.close();
- }
-
- private int getFillPictureRefCount(HSLFShape shape, HSLFFill fill) {
- AbstractEscherOptRecord opt = shape.getEscherOptRecord();
- EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__PATTERNTEXTURE);
- if(p != null) {
- int idx = p.getPropertyValue();
-
- HSLFSheet sheet = shape.getSheet();
- HSLFSlideShow ppt = sheet.getSlideShow();
- Document doc = ppt.getDocumentRecord();
- EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer();
- EscherContainerRecord bstore = HSLFShape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER);
- List<EscherRecord> lst = bstore.getChildRecords();
- return ((EscherBSERecord)lst.get(idx-1)).getRef();
- }
- return 0;
- }
-
-}
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());
}
@RunWith(Suite.class)
@Suite.SuiteClasses({
TestAddingSlides.class,
+ TestBackground.class,
TestBugs.class,
TestCounts.class,
TestMostRecentRecords.class,
--- /dev/null
+/* ====================================================================
+ 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.hslf.usermodel;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.awt.Color;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.ddf.AbstractEscherOptRecord;
+import org.apache.poi.ddf.EscherBSERecord;
+import org.apache.poi.ddf.EscherContainerRecord;
+import org.apache.poi.ddf.EscherProperties;
+import org.apache.poi.ddf.EscherRecord;
+import org.apache.poi.ddf.EscherSimpleProperty;
+import org.apache.poi.hslf.HSLFTestDataSamples;
+import org.apache.poi.hslf.record.Document;
+import org.apache.poi.hslf.usermodel.HSLFAutoShape;
+import org.apache.poi.hslf.usermodel.HSLFFill;
+import org.apache.poi.hslf.usermodel.HSLFPictureData;
+import org.apache.poi.hslf.usermodel.HSLFShape;
+import org.apache.poi.hslf.usermodel.HSLFSheet;
+import org.apache.poi.hslf.usermodel.HSLFSlide;
+import org.apache.poi.hslf.usermodel.HSLFSlideShow;
+import org.apache.poi.sl.usermodel.PictureData.PictureType;
+import org.apache.poi.sl.usermodel.ShapeType;
+import org.junit.Test;
+
+
+/**
+ * Test <code>Fill</code> object.
+ *
+ * @author Yegor Kozlov
+ */
+public final class TestBackground {
+ private static POIDataSamples _slTests = POIDataSamples.getSlideShowInstance();
+
+ /**
+ * Default background for slide, shape and slide master.
+ */
+ @Test
+ public void defaults() throws IOException {
+ HSLFSlideShow ppt = new HSLFSlideShow();
+
+ assertEquals(HSLFFill.FILL_SOLID, ppt.getSlideMasters().get(0).getBackground().getFill().getFillType());
+
+ HSLFSlide slide = ppt.createSlide();
+ assertTrue(slide.getFollowMasterBackground());
+ assertEquals(HSLFFill.FILL_SOLID, slide.getBackground().getFill().getFillType());
+
+ HSLFShape shape = new HSLFAutoShape(ShapeType.RECT);
+ assertEquals(HSLFFill.FILL_SOLID, shape.getFill().getFillType());
+ ppt.close();
+ }
+
+ /**
+ * Read fill information from an reference ppt file
+ */
+ @Test
+ public void readBackground() throws IOException {
+ HSLFSlideShow ppt = HSLFTestDataSamples.getSlideShow("backgrounds.ppt");
+ HSLFFill fill;
+ HSLFShape shape;
+
+ List<HSLFSlide> slide = ppt.getSlides();
+
+ fill = slide.get(0).getBackground().getFill();
+ assertEquals(HSLFFill.FILL_PICTURE, fill.getFillType());
+ shape = slide.get(0).getShapes().get(0);
+ assertEquals(HSLFFill.FILL_SOLID, shape.getFill().getFillType());
+
+ fill = slide.get(1).getBackground().getFill();
+ assertEquals(HSLFFill.FILL_PATTERN, fill.getFillType());
+ shape = slide.get(1).getShapes().get(0);
+ assertEquals(HSLFFill.FILL_BACKGROUND, shape.getFill().getFillType());
+
+ fill = slide.get(2).getBackground().getFill();
+ assertEquals(HSLFFill.FILL_TEXTURE, fill.getFillType());
+ shape = slide.get(2).getShapes().get(0);
+ assertEquals(HSLFFill.FILL_PICTURE, shape.getFill().getFillType());
+
+ fill = slide.get(3).getBackground().getFill();
+ assertEquals(HSLFFill.FILL_SHADE_CENTER, fill.getFillType());
+ shape = slide.get(3).getShapes().get(0);
+ assertEquals(HSLFFill.FILL_SHADE, shape.getFill().getFillType());
+ ppt.close();
+ }
+
+ /**
+ * Create a ppt with various fill effects
+ */
+ @Test
+ public void backgroundPicture() throws IOException {
+ HSLFSlideShow ppt1 = new HSLFSlideShow();
+ HSLFSlide slide;
+ HSLFFill fill;
+ HSLFShape shape;
+ HSLFPictureData data;
+
+ //slide 1
+ slide = ppt1.createSlide();
+ slide.setFollowMasterBackground(false);
+ fill = slide.getBackground().getFill();
+ data = ppt1.addPicture(_slTests.readFile("tomcat.png"), PictureType.PNG);
+ fill.setFillType(HSLFFill.FILL_PICTURE);
+ fill.setPictureData(data);
+
+ shape = new HSLFAutoShape(ShapeType.RECT);
+ shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200));
+ fill = shape.getFill();
+ fill.setFillType(HSLFFill.FILL_SOLID);
+ slide.addShape(shape);
+
+ //slide 2
+ slide = ppt1.createSlide();
+ slide.setFollowMasterBackground(false);
+ fill = slide.getBackground().getFill();
+ data = ppt1.addPicture(_slTests.readFile("tomcat.png"), PictureType.PNG);
+ fill.setFillType(HSLFFill.FILL_PATTERN);
+ fill.setPictureData(data);
+ fill.setBackgroundColor(Color.green);
+ fill.setForegroundColor(Color.red);
+
+ shape = new HSLFAutoShape(ShapeType.RECT);
+ shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200));
+ fill = shape.getFill();
+ fill.setFillType(HSLFFill.FILL_BACKGROUND);
+ slide.addShape(shape);
+
+ //slide 3
+ slide = ppt1.createSlide();
+ slide.setFollowMasterBackground(false);
+ fill = slide.getBackground().getFill();
+ data = ppt1.addPicture(_slTests.readFile("tomcat.png"), PictureType.PNG);
+ fill.setFillType(HSLFFill.FILL_TEXTURE);
+ fill.setPictureData(data);
+
+ shape = new HSLFAutoShape(ShapeType.RECT);
+ shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200));
+ fill = shape.getFill();
+ fill.setFillType(HSLFFill.FILL_PICTURE);
+ data = ppt1.addPicture(_slTests.readFile("clock.jpg"), PictureType.JPEG);
+ fill.setPictureData(data);
+ slide.addShape(shape);
+
+ // slide 4
+ slide = ppt1.createSlide();
+ slide.setFollowMasterBackground(false);
+ fill = slide.getBackground().getFill();
+ fill.setFillType(HSLFFill.FILL_SHADE_CENTER);
+ fill.setBackgroundColor(Color.white);
+ fill.setForegroundColor(Color.darkGray);
+
+ shape = new HSLFAutoShape(ShapeType.RECT);
+ shape.setAnchor(new java.awt.Rectangle(100, 100, 200, 200));
+ fill = shape.getFill();
+ fill.setFillType(HSLFFill.FILL_SHADE);
+ fill.setBackgroundColor(Color.red);
+ fill.setForegroundColor(Color.green);
+ slide.addShape(shape);
+
+ //serialize and read again
+ HSLFSlideShow ppt2 = HSLFTestDataSamples.writeOutAndReadBack(ppt1);
+ List<HSLFSlide> slides = ppt2.getSlides();
+
+ fill = slides.get(0).getBackground().getFill();
+ assertEquals(HSLFFill.FILL_PICTURE, fill.getFillType());
+ assertEquals(3, getFillPictureRefCount(slides.get(0).getBackground(), fill));
+ shape = slides.get(0).getShapes().get(0);
+ assertEquals(HSLFFill.FILL_SOLID, shape.getFill().getFillType());
+
+ fill = slides.get(1).getBackground().getFill();
+ assertEquals(HSLFFill.FILL_PATTERN, fill.getFillType());
+ shape = slides.get(1).getShapes().get(0);
+ assertEquals(HSLFFill.FILL_BACKGROUND, shape.getFill().getFillType());
+
+ fill = slides.get(2).getBackground().getFill();
+ assertEquals(HSLFFill.FILL_TEXTURE, fill.getFillType());
+ assertEquals(3, getFillPictureRefCount(slides.get(2).getBackground(), fill));
+ shape = slides.get(2).getShapes().get(0);
+ assertEquals(HSLFFill.FILL_PICTURE, shape.getFill().getFillType());
+ assertEquals(1, getFillPictureRefCount(shape, fill));
+
+ fill = slides.get(3).getBackground().getFill();
+ assertEquals(HSLFFill.FILL_SHADE_CENTER, fill.getFillType());
+ shape = slides.get(3).getShapes().get(0);
+ assertEquals(HSLFFill.FILL_SHADE, shape.getFill().getFillType());
+ ppt2.close();
+ ppt1.close();
+ }
+
+ private int getFillPictureRefCount(HSLFShape shape, HSLFFill fill) {
+ AbstractEscherOptRecord opt = shape.getEscherOptRecord();
+ EscherSimpleProperty p = HSLFShape.getEscherProperty(opt, EscherProperties.FILL__PATTERNTEXTURE);
+ if(p != null) {
+ int idx = p.getPropertyValue();
+
+ HSLFSheet sheet = shape.getSheet();
+ HSLFSlideShow ppt = sheet.getSlideShow();
+ Document doc = ppt.getDocumentRecord();
+ EscherContainerRecord dggContainer = doc.getPPDrawingGroup().getDggContainer();
+ EscherContainerRecord bstore = HSLFShape.getEscherChild(dggContainer, EscherContainerRecord.BSTORE_CONTAINER);
+ List<EscherRecord> lst = bstore.getChildRecords();
+ return ((EscherBSERecord)lst.get(idx-1)).getRef();
+ }
+ return 0;
+ }
+
+}
--- /dev/null
+/* ====================================================================
+ 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));
+ }
+ }
+}
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;
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)));
+ }
}
--- /dev/null
+/* ====================================================================
+ 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);
+ }
+}
*/
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;
}