#62921 - Provide OOXMLLite alternative for Java 12+
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1846809 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
84cc4cc1f2
commit
0d052def85
147
build.xml
147
build.xml
@ -130,8 +130,12 @@ under the License.
|
|||||||
<property name="ooxml.output.dir" location="build/ooxml-classes"/>
|
<property name="ooxml.output.dir" location="build/ooxml-classes"/>
|
||||||
<property name="ooxml.output.test.dir" location="build/ooxml-test-classes"/>
|
<property name="ooxml.output.test.dir" location="build/ooxml-test-classes"/>
|
||||||
<property name="ooxml.testokfile" location="build/ooxml-testokfile.txt"/>
|
<property name="ooxml.testokfile" location="build/ooxml-testokfile.txt"/>
|
||||||
<property name="ooxml.lite.output.dir" location="build/ooxml-lite-classes"/>
|
|
||||||
<property name="ooxml.lite.testokfile" location="build/ooxml-lite-testokfile.txt"/>
|
<property name="ooxml.lite.agent" location="build/ooxml-lite-agent.jar"/>
|
||||||
|
<property name="ooxml.lite.report" location="build/ooxml-lite-report.txt"/>
|
||||||
|
<property name="ooxml.lite.jar" location="build/ooxml-lite-classes.jar"/>
|
||||||
|
<property name="ooxml.lite.includes" value="^(com/microsoft/schemas|org/(etsi|openxmlformats|w3/)|schemaorg_apache_xmlbeans)"/>
|
||||||
|
|
||||||
|
|
||||||
<!-- Integration testing: -->
|
<!-- Integration testing: -->
|
||||||
<property name="integration.src.test" location="src/integrationtest"/>
|
<property name="integration.src.test" location="src/integrationtest"/>
|
||||||
@ -397,7 +401,8 @@ under the License.
|
|||||||
|
|
||||||
<path id="ooxml-lite.classpath">
|
<path id="ooxml-lite.classpath">
|
||||||
<path refid="ooxml.base.classpath"/>
|
<path refid="ooxml.base.classpath"/>
|
||||||
<pathelement location="${ooxml.lite.output.dir}"/> <!-- instead of ooxml-xsds.jar use the filtered classes-->
|
<!-- instead of ooxml-xsds.jar use the filtered classes-->
|
||||||
|
<pathelement location="${ooxml.lite.jar}"/>
|
||||||
<pathelement location="${ooxml.output.dir}"/>
|
<pathelement location="${ooxml.output.dir}"/>
|
||||||
<pathelement location="${ooxml.output.test.dir}"/>
|
<pathelement location="${ooxml.output.test.dir}"/>
|
||||||
<pathelement location="${main.output.test.dir}"/>
|
<pathelement location="${main.output.test.dir}"/>
|
||||||
@ -1015,8 +1020,6 @@ under the License.
|
|||||||
compile-scratchpad, compile-examples, compile-excelant"
|
compile-scratchpad, compile-examples, compile-excelant"
|
||||||
description="Compiles the POI main classes, scratchpad and examples"/>
|
description="Compiles the POI main classes, scratchpad and examples"/>
|
||||||
|
|
||||||
<target name="compile-all" depends="compile,compile-ooxml-lite"/>
|
|
||||||
|
|
||||||
<target name="compile-main" depends="init">
|
<target name="compile-main" depends="init">
|
||||||
<!-- compile the sources -->
|
<!-- compile the sources -->
|
||||||
<javac target="${jdk.version.class}"
|
<javac target="${jdk.version.class}"
|
||||||
@ -1338,7 +1341,7 @@ under the License.
|
|||||||
<!-- Section: test (execute junit tests on test suites) -->
|
<!-- Section: test (execute junit tests on test suites) -->
|
||||||
<target name="test" depends="compile,jacocotask,test-main,test-scratchpad,test-ooxml,test-excelant"
|
<target name="test" depends="compile,jacocotask,test-main,test-scratchpad,test-ooxml,test-excelant"
|
||||||
description="Tests main, scratchpad and ooxml"/>
|
description="Tests main, scratchpad and ooxml"/>
|
||||||
<target name="test-all" depends="test,test-ooxml-lite,testcoveragereport"
|
<target name="test-all" depends="test,test-integration,test-ooxml-lite,testcoveragereport"
|
||||||
description="Tests main, scratchpad, ooxml, ooxml-lite, and coveragereport"/>
|
description="Tests main, scratchpad, ooxml, ooxml-lite, and coveragereport"/>
|
||||||
|
|
||||||
<target name="testcoveragereport" depends="init,jacocotask" description="create test-report" xmlns:jacoco="antlib:org.jacoco.ant" if="coverage.enabled">
|
<target name="testcoveragereport" depends="init,jacocotask" description="create test-report" xmlns:jacoco="antlib:org.jacoco.ant" if="coverage.enabled">
|
||||||
@ -1385,9 +1388,7 @@ under the License.
|
|||||||
<group name="OOXML">
|
<group name="OOXML">
|
||||||
<classfiles>
|
<classfiles>
|
||||||
<fileset dir="${ooxml.output.dir}"/>
|
<fileset dir="${ooxml.output.dir}"/>
|
||||||
<!-- there are no actual POI classes in build/ooxml-lite-classes, only generated code...
|
<!-- there are no actual POI classes in build/ooxml-lite-classes, only generated code... -->
|
||||||
<fileset dir="${ooxml.lite.output.dir}"/>
|
|
||||||
-->
|
|
||||||
</classfiles>
|
</classfiles>
|
||||||
<sourcefiles encoding="UTF-8">
|
<sourcefiles encoding="UTF-8">
|
||||||
<fileset dir="${ooxml.src}"/>
|
<fileset dir="${ooxml.src}"/>
|
||||||
@ -1564,6 +1565,7 @@ under the License.
|
|||||||
<sysproperty key="java.io.tmpdir" value="${tempdir}"/>
|
<sysproperty key="java.io.tmpdir" value="${tempdir}"/>
|
||||||
<jvmarg value="-Xmx768M"/>
|
<jvmarg value="-Xmx768M"/>
|
||||||
<jvmarg value="-ea"/>
|
<jvmarg value="-ea"/>
|
||||||
|
<jvmarg value="-javaagent:${ooxml.lite.agent}=${ooxml.lite.report}|${ooxml.lite.includes}"/>
|
||||||
<jvmarg value="${java9addmods}" />
|
<jvmarg value="${java9addmods}" />
|
||||||
<jvmarg value="${java9addmodsvalue}" />
|
<jvmarg value="${java9addmodsvalue}" />
|
||||||
<jvmarg value="${java9addopens1}" />
|
<jvmarg value="${java9addopens1}" />
|
||||||
@ -1598,6 +1600,7 @@ under the License.
|
|||||||
</classpath>
|
</classpath>
|
||||||
<syspropertyset refid="junit.properties"/>
|
<syspropertyset refid="junit.properties"/>
|
||||||
<sysproperty key="java.io.tmpdir" value="${tempdir}"/>
|
<sysproperty key="java.io.tmpdir" value="${tempdir}"/>
|
||||||
|
<jvmarg value="-javaagent:${ooxml.lite.agent}=${ooxml.lite.report}|${ooxml.lite.includes}"/>
|
||||||
<jvmarg value="-Xmx768M"/>
|
<jvmarg value="-Xmx768M"/>
|
||||||
<jvmarg value="-ea"/>
|
<jvmarg value="-ea"/>
|
||||||
<jvmarg value="${java9addmods}" />
|
<jvmarg value="${java9addmods}" />
|
||||||
@ -1620,7 +1623,7 @@ under the License.
|
|||||||
</sequential>
|
</sequential>
|
||||||
</macrodef>
|
</macrodef>
|
||||||
|
|
||||||
<target name="test-ooxml" depends="compile-main,compile-ooxml,-test-ooxml-check,jacocotask" unless="ooxml.test.notRequired"
|
<target name="test-ooxml" depends="compile-main,compile-ooxml,-test-ooxml-check,jacocotask,-ooxml-lite-agent" unless="ooxml.test.notRequired"
|
||||||
description="test OOXML classes">
|
description="test OOXML classes">
|
||||||
<ooxml-test-runner classpath="test.ooxml.classpath" type="ooxml"/>
|
<ooxml-test-runner classpath="test.ooxml.classpath" type="ooxml"/>
|
||||||
<delete file="${ooxml.testokfile}"/>
|
<delete file="${ooxml.testokfile}"/>
|
||||||
@ -1638,7 +1641,7 @@ under the License.
|
|||||||
</uptodate>
|
</uptodate>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="test-integration" depends="compile-integration,-test-integration-check,jacocotask"
|
<target name="test-integration" depends="compile-integration,-test-integration-check,jacocotask,-ooxml-lite-agent"
|
||||||
unless="integration.test.notRequired" xmlns:jacoco="antlib:org.jacoco.ant">
|
unless="integration.test.notRequired" xmlns:jacoco="antlib:org.jacoco.ant">
|
||||||
<propertyreset name="org.apache.poi.util.POILogger" value="org.apache.poi.util.CommonsLogger"/>
|
<propertyreset name="org.apache.poi.util.POILogger" value="org.apache.poi.util.CommonsLogger"/>
|
||||||
<delete dir="build" includes="test-integration.log*"/>
|
<delete dir="build" includes="test-integration.log*"/>
|
||||||
@ -1650,6 +1653,7 @@ under the License.
|
|||||||
<sysproperty key="java.io.tmpdir" value="${tempdir}"/>
|
<sysproperty key="java.io.tmpdir" value="${tempdir}"/>
|
||||||
<jvmarg value="-ea"/>
|
<jvmarg value="-ea"/>
|
||||||
<jvmarg value="-Xmx1512M"/>
|
<jvmarg value="-Xmx1512M"/>
|
||||||
|
<jvmarg value="-javaagent:${ooxml.lite.agent}=${ooxml.lite.report}|${ooxml.lite.includes}"/>
|
||||||
<jvmarg value="${java9addmods}" />
|
<jvmarg value="${java9addmods}" />
|
||||||
<jvmarg value="${java9addmodsvalue}" />
|
<jvmarg value="${java9addmodsvalue}" />
|
||||||
<jvmarg value="${java9addopens1}" />
|
<jvmarg value="${java9addopens1}" />
|
||||||
@ -1677,57 +1681,28 @@ under the License.
|
|||||||
<echo file="${integration.testokfile}" append="false" message="testok"/>
|
<echo file="${integration.testokfile}" append="false" message="testok"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!-- Section: test-ooxml-lite -->
|
<!-- the ooxml lite agent collects referenced schema files while other junit tests are run, -->
|
||||||
<target name="-compile-ooxml-lite-check">
|
<!-- therefore its best to compile the ooxml lite jar after all usual tests are done -->
|
||||||
<uptodate property="ooxml.lite.test.notRequired" targetfile="${ooxml.lite.testokfile}">
|
<target name="compile-ooxml-lite" depends="compile-ooxml,-ooxml-lite-agent,test-ooxml">
|
||||||
<srcfiles dir="${ooxml.src}"/>
|
<echo message="Create ooxml-lite schemas"/>
|
||||||
<srcfiles dir="${ooxml.src.test}"/>
|
|
||||||
<srcfiles file="${ooxml.xsds.jar}"/>
|
|
||||||
<srcfiles file="${ooxml.security.jar}"/>
|
|
||||||
</uptodate>
|
|
||||||
</target>
|
|
||||||
|
|
||||||
<target name="compile-ooxml-lite" depends="-compile-ooxml-lite-check,compile-ooxml"
|
<copy file="${ooxml.lite.report}" tofile="${ooxml.lite.report}-pat" overwrite="true"/>
|
||||||
unless="ooxml.lite.test.notRequired">
|
<replaceregexp file="${ooxml.lite.report}-pat" byline="true" match="(.*)" replace="\1.class${line.separator}\1$*.class"/>
|
||||||
<delete file="${ooxml.lite.testokfile}"/>
|
|
||||||
<echo message="Running ooxml-lite generator"/>
|
|
||||||
|
|
||||||
<property name="ooxml.lite-merged.dir" location="build/ooxml-lite-merged"/>
|
<patternset id="xsbfiles">
|
||||||
<mkdir dir="${ooxml.lite-merged.dir}"/>
|
<includesfile name="${ooxml.lite.report}-pat"/>
|
||||||
|
<include name="schemaorg_apache_xmlbeans/system/**/*.xsb"/>
|
||||||
|
<include name="schemaorg_apache_xmlbeans/element/**/*.xsb"/>
|
||||||
|
</patternset>
|
||||||
|
|
||||||
<jar destfile="${ooxml.lite-merged.dir}/ooxml-lite-merged.jar">
|
<jar destfile="${ooxml.lite.jar}" duplicate="preserve">
|
||||||
<zipfileset includes="**/*" src="${ooxml.xsds.jar}"/>
|
<zipfileset src="${ooxml.xsds.jar}">
|
||||||
<zipfileset includes="**/*" src="${ooxml.security.jar}"/>
|
<patternset refid="xsbfiles"/>
|
||||||
|
</zipfileset>
|
||||||
|
<zipfileset src="${ooxml.security.jar}">
|
||||||
|
<patternset refid="xsbfiles"/>
|
||||||
|
</zipfileset>
|
||||||
</jar>
|
</jar>
|
||||||
|
|
||||||
<java classname="org.apache.poi.ooxml.util.OOXMLLite" fork="yes"
|
|
||||||
failonerror="true">
|
|
||||||
<classpath>
|
|
||||||
<pathelement path="${ooxml.lite-merged.dir}/ooxml-lite-merged.jar"/>
|
|
||||||
</classpath>
|
|
||||||
<classpath refid="test.ooxml.classpath"/>
|
|
||||||
<classpath refid="ooxml.xmlsec.classpath"/>
|
|
||||||
<syspropertyset refid="junit.properties"/>
|
|
||||||
<sysproperty key="java.io.tmpdir" value="${tempdir}"/>
|
|
||||||
<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}" />
|
|
||||||
<jvmarg value="${file.leak.detector}" />
|
|
||||||
<arg value="-ooxml"/>
|
|
||||||
<arg value="${ooxml.lite-merged.dir}/ooxml-lite-merged.jar"/>
|
|
||||||
<arg value="-test"/>
|
|
||||||
<arg value="${ooxml.output.test.dir}"/>
|
|
||||||
<arg value="-dest"/>
|
|
||||||
<arg value="${ooxml.lite.output.dir}"/>
|
|
||||||
</java>
|
|
||||||
|
|
||||||
<echo file="${ooxml.lite.testokfile}" append="false" message="testok"/>
|
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="test-ooxml-lite" depends="jacocotask,compile-ooxml-xsds,compile-ooxml-lite">
|
<target name="test-ooxml-lite" depends="jacocotask,compile-ooxml-xsds,compile-ooxml-lite">
|
||||||
@ -1736,6 +1711,15 @@ under the License.
|
|||||||
<ooxml-test-runner classpath="ooxml-lite.classpath" type="ooxml-lite"/>
|
<ooxml-test-runner classpath="ooxml-lite.classpath" type="ooxml-lite"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
|
<target name="-ooxml-lite-agent" depends="jacocotask,compile-ooxml-xsds,compile-ooxml">
|
||||||
|
<jar destfile="${ooxml.lite.agent}">
|
||||||
|
<fileset dir="${ooxml.output.test.dir}" includes="org/apache/poi/ooxml/util/OOXMLLiteAgent*.class"/>
|
||||||
|
<manifest>
|
||||||
|
<attribute name="Premain-Class" value="org.apache.poi.ooxml.util.OOXMLLiteAgent"/>
|
||||||
|
</manifest>
|
||||||
|
</jar>
|
||||||
|
</target>
|
||||||
|
|
||||||
<!-- Section: test-excelant -->
|
<!-- Section: test-excelant -->
|
||||||
<target name="-test-excelant-check">
|
<target name="-test-excelant-check">
|
||||||
<uptodate property="excelant.test.notRequired" targetfile="${excelant.testokfile}">
|
<uptodate property="excelant.test.notRequired" targetfile="${excelant.testokfile}">
|
||||||
@ -1953,11 +1937,11 @@ under the License.
|
|||||||
</target>
|
</target>
|
||||||
|
|
||||||
<macrodef name="maven-jar">
|
<macrodef name="maven-jar">
|
||||||
<attribute name="dir"/>
|
<attribute name="src"/>
|
||||||
<sequential>
|
<sequential>
|
||||||
<local name="destfile"/>
|
<local name="destfile"/>
|
||||||
<pathconvert property="destfile" targetos="unix">
|
<pathconvert property="destfile" targetos="unix">
|
||||||
<path><pathelement path="@{dir}"/></path>
|
<path><pathelement path="@{src}"/></path>
|
||||||
<mapper>
|
<mapper>
|
||||||
<chainedmapper>
|
<chainedmapper>
|
||||||
<filtermapper>
|
<filtermapper>
|
||||||
@ -1971,33 +1955,39 @@ under the License.
|
|||||||
</chainedmapper>
|
</chainedmapper>
|
||||||
</mapper>
|
</mapper>
|
||||||
</pathconvert>
|
</pathconvert>
|
||||||
|
<local name="isjar"/>
|
||||||
|
<condition property="isjar">
|
||||||
|
<contains string="@{src}" substring=".jar"/>
|
||||||
|
</condition>
|
||||||
|
|
||||||
<jar destfile="build/dist/maven/${destfile}.jar"
|
<jar destfile="build/dist/maven/${destfile}.jar"
|
||||||
manifest="build/poi-manifest.mf">
|
manifest="build/poi-manifest.mf">
|
||||||
<fileset dir="@{dir}"/>
|
<fileset dir="@{src}" unless:true="${isjar}"/>
|
||||||
|
<zipfileset src="@{src}" if:true="${isjar}"/>
|
||||||
<metainf dir="legal/"/>
|
<metainf dir="legal/"/>
|
||||||
</jar>
|
</jar>
|
||||||
</sequential>
|
</sequential>
|
||||||
</macrodef>
|
</macrodef>
|
||||||
|
|
||||||
<target name="jar" depends="compile-all, compile-version, -manifest" description="Creates jar files for distribution">
|
<target name="jar" depends="compile, compile-version, -manifest" description="Creates jar files for distribution">
|
||||||
<maven-jar dir="${main.output.dir}"/>
|
<maven-jar src="${main.output.dir}"/>
|
||||||
<maven-jar dir="${scratchpad.output.dir}"/>
|
<maven-jar src="${scratchpad.output.dir}"/>
|
||||||
<maven-jar dir="${ooxml.output.dir}"/>
|
<maven-jar src="${ooxml.output.dir}"/>
|
||||||
<maven-jar dir="${examples.output.dir}"/>
|
<maven-jar src="${examples.output.dir}"/>
|
||||||
<maven-jar dir="${excelant.output.dir}"/>
|
<maven-jar src="${excelant.output.dir}"/>
|
||||||
<maven-jar dir="${ooxml.lite.output.dir}"/>
|
<maven-jar src="${ooxml.lite.jar}"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="jar-src" depends="compile-all, compile-version, -manifest" description="Sources for Maven">
|
<target name="jar-src" depends="compile, compile-version, -manifest" description="Sources for Maven">
|
||||||
<maven-jar dir="${main.src}"/>
|
<maven-jar src="${main.src}"/>
|
||||||
<maven-jar dir="${scratchpad.src}"/>
|
<maven-jar src="${scratchpad.src}"/>
|
||||||
<maven-jar dir="${ooxml.src}"/>
|
<maven-jar src="${ooxml.src}"/>
|
||||||
<maven-jar dir="${examples.src}"/>
|
<maven-jar src="${examples.src}"/>
|
||||||
<maven-jar dir="${excelant.src}"/>
|
<maven-jar src="${excelant.src}"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="integration-test-jar" depends="compile-integration,-manifest" description="target for packaging the integration-test code for mass regression test runs">
|
<target name="integration-test-jar" depends="compile-integration,-manifest" description="target for packaging the integration-test code for mass regression test runs">
|
||||||
<maven-jar dir="${integration.output.test.dir}"/>
|
<maven-jar src="${integration.output.test.dir}"/>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="-do-jar-check-javadocs-package-list">
|
<target name="-do-jar-check-javadocs-package-list">
|
||||||
@ -2112,6 +2102,7 @@ under the License.
|
|||||||
lib/**,
|
lib/**,
|
||||||
bin/**,
|
bin/**,
|
||||||
out/**,
|
out/**,
|
||||||
|
tmp/**,
|
||||||
sonar/**/target/**,
|
sonar/**/target/**,
|
||||||
sonar/*/src/**,
|
sonar/*/src/**,
|
||||||
compile-lib/**,
|
compile-lib/**,
|
||||||
@ -2167,14 +2158,12 @@ under the License.
|
|||||||
</mvn:mvn>
|
</mvn:mvn>
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<target name="dist" depends="clean, compile-all, test-all, rat-check, forbidden-apis-check, docs, jar, release-notes, assemble"
|
<target name="dist" depends="clean, compile, test-all, rat-check, forbidden-apis-check, docs, jar, release-notes, assemble"
|
||||||
description="Creates the entire distribution into build/dist, from scratch">
|
description="Creates the entire distribution into build/dist, from scratch">
|
||||||
</target>
|
</target>
|
||||||
|
|
||||||
<!-- continuous integration targets -->
|
<!-- continuous integration targets -->
|
||||||
<target name="gump" depends="compile-all, test-all, jar"
|
<target name="jenkins" depends="compile, test-all, jar, javadocs, assemble, findbugs, release-notes, rat-check, forbidden-apis-check"
|
||||||
description="Target for running with Apache Gump continuous integration. Builds and tests POI and generates jar artifacts." />
|
|
||||||
<target name="jenkins" depends="compile-all, test-all, test-integration, jar, javadocs, assemble, findbugs, release-notes, rat-check, forbidden-apis-check"
|
|
||||||
description="Target run by Jenkins on a continuous basis. Builds and tests POI, generates artifacts and documentation, and searches for problems."/>
|
description="Target run by Jenkins on a continuous basis. Builds and tests POI, generates artifacts and documentation, and searches for problems."/>
|
||||||
|
|
||||||
<available property="maven.ant.tasks.present" classname="org.apache.maven.artifact.ant.Pom"/>
|
<available property="maven.ant.tasks.present" classname="org.apache.maven.artifact.ant.Pom"/>
|
||||||
|
@ -1,375 +0,0 @@
|
|||||||
/* ====================================================================
|
|
||||||
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.ooxml.util;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.security.AccessController;
|
|
||||||
import java.security.CodeSource;
|
|
||||||
import java.security.PrivilegedAction;
|
|
||||||
import java.security.ProtectionDomain;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.Vector;
|
|
||||||
import java.util.jar.JarEntry;
|
|
||||||
import java.util.jar.JarFile;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import org.apache.poi.util.IOUtils;
|
|
||||||
import org.apache.poi.util.StringUtil;
|
|
||||||
import org.apache.poi.util.SuppressForbidden;
|
|
||||||
import org.apache.xmlbeans.StringEnumAbstractBase;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.internal.TextListener;
|
|
||||||
import org.junit.runner.Description;
|
|
||||||
import org.junit.runner.JUnitCore;
|
|
||||||
import org.junit.runner.Result;
|
|
||||||
import org.reflections.Reflections;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build a 'lite' version of the ooxml-schemas.jar
|
|
||||||
*
|
|
||||||
* @author Yegor Kozlov
|
|
||||||
*/
|
|
||||||
public final class OOXMLLite {
|
|
||||||
private static final Pattern SCHEMA_PATTERN = Pattern.compile("schemaorg_apache_xmlbeans/(system|element)/.*\\.xsb");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Destination directory to copy filtered classes
|
|
||||||
*/
|
|
||||||
private File _destDest;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Directory with the compiled ooxml tests
|
|
||||||
*/
|
|
||||||
private File _testDir;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reference to the ooxml-schemas.jar
|
|
||||||
*/
|
|
||||||
private File _ooxmlJar;
|
|
||||||
|
|
||||||
|
|
||||||
OOXMLLite(String dest, String test, String ooxmlJar) {
|
|
||||||
_destDest = new File(dest);
|
|
||||||
_testDir = new File(test);
|
|
||||||
_ooxmlJar = new File(ooxmlJar);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) throws IOException {
|
|
||||||
System.out.println("Free memory (bytes): " +
|
|
||||||
Runtime.getRuntime().freeMemory());
|
|
||||||
long maxMemory = Runtime.getRuntime().maxMemory();
|
|
||||||
System.out.println("Maximum memory (bytes): " +
|
|
||||||
(maxMemory == Long.MAX_VALUE ? "no limit" : maxMemory));
|
|
||||||
System.out.println("Total memory (bytes): " +
|
|
||||||
Runtime.getRuntime().totalMemory());
|
|
||||||
|
|
||||||
String dest = null, test = null, ooxml = null;
|
|
||||||
|
|
||||||
for (int i = 0; i < args.length; i++) {
|
|
||||||
switch (args[i]) {
|
|
||||||
case "-dest":
|
|
||||||
dest = args[++i]; // lgtm[java/index-out-of-bounds]
|
|
||||||
break;
|
|
||||||
case "-test":
|
|
||||||
test = args[++i]; // lgtm[java/index-out-of-bounds]
|
|
||||||
break;
|
|
||||||
case "-ooxml":
|
|
||||||
ooxml = args[++i]; // lgtm[java/index-out-of-bounds]
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OOXMLLite builder = new OOXMLLite(dest, test, ooxml);
|
|
||||||
builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
void build() throws IOException {
|
|
||||||
List<Class<?>> lst = new ArrayList<>();
|
|
||||||
//collect unit tests
|
|
||||||
String exclude = StringUtil.join("|",
|
|
||||||
"BaseTestXWorkbook",
|
|
||||||
"BaseTestXSheet",
|
|
||||||
"BaseTestXRow",
|
|
||||||
"BaseTestXCell",
|
|
||||||
"BaseTestXSSFPivotTable",
|
|
||||||
"TestSXSSFWorkbook\\$\\d",
|
|
||||||
"TestUnfixedBugs",
|
|
||||||
"MemoryUsage",
|
|
||||||
"TestDataProvider",
|
|
||||||
"TestDataSamples",
|
|
||||||
"All.+Tests",
|
|
||||||
"ZipFileAssert",
|
|
||||||
"AesZipFileZipEntrySource",
|
|
||||||
"TempFileRecordingSXSSFWorkbookWithCustomZipEntrySource",
|
|
||||||
"PkiTestUtils",
|
|
||||||
"TestCellFormatPart\\$\\d",
|
|
||||||
"TestSignatureInfo\\$\\d",
|
|
||||||
"TestCertificateEncryption\\$CertData",
|
|
||||||
"TestPOIXMLDocument\\$OPCParser",
|
|
||||||
"TestPOIXMLDocument\\$TestFactory",
|
|
||||||
"TestXSLFTextParagraph\\$DrawTextParagraphProxy",
|
|
||||||
"TestXSSFExportToXML\\$\\d",
|
|
||||||
"TestXSSFExportToXML\\$DummyEntityResolver",
|
|
||||||
"TestFormulaEvaluatorOnXSSF\\$Result",
|
|
||||||
"TestFormulaEvaluatorOnXSSF\\$SS",
|
|
||||||
"TestMultiSheetFormulaEvaluatorOnXSSF\\$Result",
|
|
||||||
"TestMultiSheetFormulaEvaluatorOnXSSF\\$SS",
|
|
||||||
"TestXSSFBugs\\$\\d",
|
|
||||||
"AddImageBench",
|
|
||||||
"AddImageBench_jmhType_B\\d",
|
|
||||||
"AddImageBench_benchCreatePicture_jmhTest",
|
|
||||||
"TestEvilUnclosedBRFixingInputStream\\$EvilUnclosedBRFixingInputStream",
|
|
||||||
"TempFileRecordingSXSSFWorkbookWithCustomZipEntrySource\\$TempFileRecordingSheetDataWriterWithDecorator",
|
|
||||||
"TestXSSFBReader\\$1",
|
|
||||||
"TestXSSFBReader\\$TestSheetHandler",
|
|
||||||
"TestFormulaEvaluatorOnXSSF\\$1",
|
|
||||||
"TestMultiSheetFormulaEvaluatorOnXSSF\\$1",
|
|
||||||
"TestZipPackagePropertiesMarshaller\\$1",
|
|
||||||
"SLCommonUtils",
|
|
||||||
"TestPPTX2PNG\\$1",
|
|
||||||
"TestMatrixFormulasFromXMLSpreadsheet\\$1",
|
|
||||||
"TestMatrixFormulasFromXMLSpreadsheet\\$Navigator",
|
|
||||||
"TestPOIXMLDocument\\$UncaughtHandler",
|
|
||||||
"TestOleShape\\$Api",
|
|
||||||
"TestOleShape\\$1",
|
|
||||||
"TestPOIXMLDocument\\$1",
|
|
||||||
"TestXMLSlideShow\\$1",
|
|
||||||
"TestXMLSlideShow\\$BufAccessBAOS",
|
|
||||||
"TestXDDFChart\\$1",
|
|
||||||
"TestOOXMLLister\\$1",
|
|
||||||
"TestOOXMLPrettyPrint\\$1"
|
|
||||||
);
|
|
||||||
System.out.println("Collecting unit tests from " + _testDir);
|
|
||||||
collectTests(_testDir, _testDir, lst, ".+.class$", ".+(" + exclude + ").class");
|
|
||||||
System.out.println("Found " + lst.size() + " classes");
|
|
||||||
|
|
||||||
//run tests
|
|
||||||
JUnitCore jUnitCore = new JUnitCore();
|
|
||||||
jUnitCore.addListener(new TextListener(System.out) {
|
|
||||||
private final Set<String> classes = new HashSet<>();
|
|
||||||
private int count;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void testStarted(Description description) {
|
|
||||||
// count how many test-classes we already saw
|
|
||||||
classes.add(description.getClassName());
|
|
||||||
count++;
|
|
||||||
if(count % 100 == 0) {
|
|
||||||
System.out.println();
|
|
||||||
System.out.println(classes.size() + "/" + lst.size() + ": " + description.getDisplayName());
|
|
||||||
}
|
|
||||||
|
|
||||||
super.testStarted(description);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Result result = jUnitCore.run(lst.toArray(new Class<?>[0]));
|
|
||||||
if (!result.wasSuccessful()) {
|
|
||||||
throw new RuntimeException("Tests did not succeed, cannot build ooxml-lite jar");
|
|
||||||
}
|
|
||||||
|
|
||||||
//see what classes from the ooxml-schemas.jar are loaded
|
|
||||||
System.out.println("Copying classes to " + _destDest);
|
|
||||||
Set<Class<?>> classes = getLoadedClasses(_ooxmlJar.getName());
|
|
||||||
Set<String> packages = new HashSet<>();
|
|
||||||
for (Class<?> cls : classes) {
|
|
||||||
copyFile(cls);
|
|
||||||
packages.add(cls.getPackage().getName());
|
|
||||||
|
|
||||||
if (cls.isInterface()) {
|
|
||||||
/// Copy classes and interfaces declared as members of this class
|
|
||||||
for (Class<?> fc : cls.getDeclaredClasses()) {
|
|
||||||
copyFile(fc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (String pkg : packages) {
|
|
||||||
Reflections reflections = new Reflections(pkg);
|
|
||||||
Set<Class<? extends List>> listClasses = reflections.getSubTypesOf(List.class);
|
|
||||||
listClasses.removeAll(classes);
|
|
||||||
for (Class listClass : listClasses) {
|
|
||||||
for (Class<?> compare : classes) {
|
|
||||||
if (listClass.getName().startsWith(compare.getName())) {
|
|
||||||
copyFile(listClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Set<Class<? extends StringEnumAbstractBase>> enumClasses = reflections.getSubTypesOf(StringEnumAbstractBase.class);
|
|
||||||
listClasses.removeAll(classes);
|
|
||||||
for (Class enumClass : enumClasses) {
|
|
||||||
for (Class<?> compare : classes) {
|
|
||||||
if (enumClass.getName().startsWith(compare.getName())) {
|
|
||||||
copyFile(enumClass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//finally copy the compiled .xsb files
|
|
||||||
System.out.println("Copying .xsb resources");
|
|
||||||
try (JarFile jar = new JarFile(_ooxmlJar)) {
|
|
||||||
for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements(); ) {
|
|
||||||
JarEntry je = e.nextElement();
|
|
||||||
if (SCHEMA_PATTERN.matcher(je.getName()).matches()) {
|
|
||||||
File destFile = new File(_destDest, je.getName());
|
|
||||||
IOUtils.copy(jar.getInputStream(je), destFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void copyFile(Class<?> cls) throws IOException {
|
|
||||||
String className = cls.getName();
|
|
||||||
String classRef = className.replace('.', '/') + ".class";
|
|
||||||
File destFile = new File(_destDest, classRef);
|
|
||||||
IOUtils.copy(cls.getResourceAsStream('/' + classRef), destFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean checkForTestAnnotation(Class<?> testclass) {
|
|
||||||
for (Method m : testclass.getDeclaredMethods()) {
|
|
||||||
if(m.isAnnotationPresent(Test.class)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// also check super classes
|
|
||||||
if(testclass.getSuperclass() != null) {
|
|
||||||
for (Method m : testclass.getSuperclass().getDeclaredMethods()) {
|
|
||||||
if(m.isAnnotationPresent(Test.class)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.println("Class " + testclass.getName() + " does not derive from TestCase and does not have a @Test annotation");
|
|
||||||
|
|
||||||
// Should we also look at superclasses to find cases
|
|
||||||
// where we have abstract base classes with derived tests?
|
|
||||||
// if(checkForTestAnnotation(testclass.getSuperclass())) return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursively collect classes from the supplied directory
|
|
||||||
*
|
|
||||||
* @param arg the directory to search in
|
|
||||||
* @param out output
|
|
||||||
* @param ptrn the pattern (regexp) to filter found files
|
|
||||||
*/
|
|
||||||
private static void collectTests(File root, File arg, List<Class<?>> out, String ptrn, String exclude) {
|
|
||||||
if (arg.isDirectory()) {
|
|
||||||
File files[] = arg.listFiles();
|
|
||||||
if (files != null) {
|
|
||||||
for (File f : files) {
|
|
||||||
collectTests(root, f, out, ptrn, exclude);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
String path = arg.getAbsolutePath();
|
|
||||||
String prefix = root.getAbsolutePath();
|
|
||||||
String cls = path.substring(prefix.length() + 1).replace(File.separator, ".");
|
|
||||||
if(!cls.matches(ptrn)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (cls.matches(exclude)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
//ignore inner classes defined in tests
|
|
||||||
if (cls.indexOf('$') != -1) {
|
|
||||||
System.out.println("Inner class " + cls + " not included");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cls = cls.replace(".class", "");
|
|
||||||
|
|
||||||
try {
|
|
||||||
Class<?> testclass = Class.forName(cls);
|
|
||||||
if (TestCase.class.isAssignableFrom(testclass)
|
|
||||||
|| checkForTestAnnotation(testclass)) {
|
|
||||||
out.add(testclass);
|
|
||||||
}
|
|
||||||
} catch (Throwable e) { // NOSONAR
|
|
||||||
System.out.println("Class " + cls + " is not in classpath");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param ptrn the pattern to filter output
|
|
||||||
* @return the classes loaded by the system class loader
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private static Set<Class<?>> getLoadedClasses(String ptrn) {
|
|
||||||
// make the field accessible, we defer this from static initialization to here to
|
|
||||||
// allow JDKs which do not have this field (e.g. IBM JDK) to at least load the class
|
|
||||||
// without failing, see https://issues.apache.org/bugzilla/show_bug.cgi?id=56550
|
|
||||||
final Field _classes = AccessController.doPrivileged(new PrivilegedAction<Field>() {
|
|
||||||
@Override
|
|
||||||
@SuppressForbidden("TODO: Reflection works until Java 8 on Oracle/Sun JDKs, but breaks afterwards (different classloader types, access checks)")
|
|
||||||
public Field run() {
|
|
||||||
try {
|
|
||||||
Field fld = ClassLoader.class.getDeclaredField("classes");
|
|
||||||
fld.setAccessible(true);
|
|
||||||
return fld;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ClassLoader appLoader = ClassLoader.getSystemClassLoader();
|
|
||||||
try {
|
|
||||||
Vector<Class<?>> classes = (Vector<Class<?>>) _classes.get(appLoader);
|
|
||||||
Set<Class<?>> set = new HashSet<>();
|
|
||||||
for (Class<?> cls : classes) {
|
|
||||||
// e.g. proxy-classes, ...
|
|
||||||
ProtectionDomain pd = cls.getProtectionDomain();
|
|
||||||
if (pd == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
CodeSource cs = pd.getCodeSource();
|
|
||||||
if (cs == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
URL loc = cs.getLocation();
|
|
||||||
if (loc == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
String jar = loc.toString();
|
|
||||||
if (jar.contains(ptrn)) {
|
|
||||||
set.add(cls);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return set;
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,78 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.ooxml.util;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.instrument.ClassFileTransformer;
|
||||||
|
import java.lang.instrument.Instrumentation;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardOpenOption;
|
||||||
|
import java.security.ProtectionDomain;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OOXMLLiteAgent is the replacement for the former OOXMLLite, because in Java 12
|
||||||
|
* it isn't possible to access the privates :) of the ClassLoader
|
||||||
|
*/
|
||||||
|
public class OOXMLLiteAgent {
|
||||||
|
|
||||||
|
static class LoggingTransformer implements ClassFileTransformer {
|
||||||
|
final Path path;
|
||||||
|
final Pattern includes;
|
||||||
|
final Set<Integer> fileHashes = new HashSet<>();
|
||||||
|
|
||||||
|
public LoggingTransformer(String agentArgs) {
|
||||||
|
String args[] = (agentArgs == null ? "" : agentArgs).split("\\|",2);
|
||||||
|
path = Paths.get(args.length >= 1 ? args[0] : "ooxml-lite.out");
|
||||||
|
includes = Pattern.compile(args.length >= 2 ? args[1] : ".*/schemas/.*");
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (Files.exists(path)) {
|
||||||
|
try (Stream<String> stream = Files.lines(path)) {
|
||||||
|
stream.forEach((s) -> fileHashes.add(s.hashCode()));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Files.createFile(path);
|
||||||
|
}
|
||||||
|
} catch (IOException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] transform(ClassLoader loader, String className, Class redefiningClass, ProtectionDomain domain, byte[] bytes) {
|
||||||
|
if (path != null && className != null && !fileHashes.contains(className.hashCode()) && includes.matcher(className).find()) {
|
||||||
|
try {
|
||||||
|
// TODO: check if this is atomic ... as transform() is probably called synchronized, it doesn't matter anyway
|
||||||
|
Files.write(path, (className+"\n").getBytes(StandardCharsets.ISO_8859_1), StandardOpenOption.APPEND);
|
||||||
|
fileHashes.add(className.hashCode());
|
||||||
|
} catch (IOException ignroed) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void premain(String agentArgs, Instrumentation inst) {
|
||||||
|
inst.addTransformer(new LoggingTransformer(agentArgs));
|
||||||
|
}
|
||||||
|
}
|
@ -41,7 +41,7 @@ public class TestCellFormatPart extends CellFormatTestBase {
|
|||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void setLocale() {
|
public static void setLocale() {
|
||||||
userLocale = LocaleUtil.getUserLocale();
|
userLocale = LocaleUtil.getUserLocale();
|
||||||
LocaleUtil.setUserLocale(Locale.ROOT);
|
LocaleUtil.setUserLocale(Locale.UK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterClass
|
@AfterClass
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
package org.apache.poi.hmef;
|
package org.apache.poi.hmef;
|
||||||
|
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
@ -83,9 +84,7 @@ public final class TestAttachments extends HMEFTest {
|
|||||||
List<Attachment> attachments = quick.getAttachments();
|
List<Attachment> attachments = quick.getAttachments();
|
||||||
|
|
||||||
// Pick a predictable date format + timezone
|
// Pick a predictable date format + timezone
|
||||||
DateFormat fmt = DateFormat.getDateTimeInstance(
|
DateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss", Locale.UK);
|
||||||
DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK
|
|
||||||
);
|
|
||||||
fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
|
fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
|
||||||
|
|
||||||
// They should all have the same date on them
|
// They should all have the same date on them
|
||||||
|
@ -20,6 +20,7 @@ package org.apache.poi.hmef.attribute;
|
|||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.apache.poi.POIDataSamples;
|
import org.apache.poi.POIDataSamples;
|
||||||
@ -159,9 +160,7 @@ protected void tearDown() throws Exception {
|
|||||||
assertEquals(MAPIDateAttribute.class, attr.getClass());
|
assertEquals(MAPIDateAttribute.class, attr.getClass());
|
||||||
|
|
||||||
MAPIDateAttribute date = (MAPIDateAttribute)attr;
|
MAPIDateAttribute date = (MAPIDateAttribute)attr;
|
||||||
DateFormat fmt = DateFormat.getDateTimeInstance(
|
DateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss", Locale.UK);
|
||||||
DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK
|
|
||||||
);
|
|
||||||
fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
|
fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
|
||||||
assertEquals("15-Dec-2010 14:46:31", fmt.format(date.getDate()));
|
assertEquals("15-Dec-2010 14:46:31", fmt.format(date.getDate()));
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ package org.apache.poi.hmef.attribute;
|
|||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.apache.poi.POIDataSamples;
|
import org.apache.poi.POIDataSamples;
|
||||||
@ -159,9 +160,7 @@ public final class TestTNEFAttributes extends TestCase {
|
|||||||
// Ask for it as a Java date, and have it converted
|
// Ask for it as a Java date, and have it converted
|
||||||
// Pick a predictable format + location + timezone
|
// Pick a predictable format + location + timezone
|
||||||
TNEFDateAttribute date = (TNEFDateAttribute)attr;
|
TNEFDateAttribute date = (TNEFDateAttribute)attr;
|
||||||
DateFormat fmt = DateFormat.getDateTimeInstance(
|
DateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss", Locale.UK);
|
||||||
DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK
|
|
||||||
);
|
|
||||||
fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
|
fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
|
||||||
assertEquals("28-Apr-2010 12:40:56", fmt.format(date.getDate()));
|
assertEquals("28-Apr-2010 12:40:56", fmt.format(date.getDate()));
|
||||||
}
|
}
|
||||||
|
@ -23,121 +23,102 @@ import java.text.DateFormatSymbols;
|
|||||||
import java.text.FieldPosition;
|
import java.text.FieldPosition;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import org.apache.poi.util.LocaleUtil;
|
import org.apache.poi.util.LocaleUtil;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
public class TestExcelStyleDateFormatter {
|
public class TestExcelStyleDateFormatter {
|
||||||
private static final String EXCEL_DATE_FORMAT = "MMMMM";
|
private static final String EXCEL_DATE_FORMAT = "MMMMM";
|
||||||
|
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd", Locale.ROOT);
|
||||||
|
private final int jreVersion;
|
||||||
|
|
||||||
|
public TestExcelStyleDateFormatter() {
|
||||||
|
jreVersion = Integer.parseInt(System.getProperty("java.version")
|
||||||
|
.replace("1.8", "8").replaceAll("(\\d+).*", "$1"));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [Bug 60369] Month format 'MMMMM' issue with TEXT-formula and Java 8
|
* [Bug 60369] Month format 'MMMMM' issue with TEXT-formula and Java 8
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void test60369() throws ParseException {
|
public void test60369() {
|
||||||
Map<Locale, List<String>> testMap = initializeLocales();
|
Map<Locale, String> testMap = initializeLocales();
|
||||||
|
|
||||||
// We have to set up dates as well.
|
// We have to set up dates as well.
|
||||||
SimpleDateFormat testDateFormat = new SimpleDateFormat("dd.MM.yyyy", Locale.ROOT);
|
List<Date> testDates = Stream.of("1980-01-12", "1995-02-11", "2045-03-10", "2016-04-09", "2017-05-08",
|
||||||
List<Date> testDates = Arrays.asList(
|
"1945-06-07", "1998-07-06", "2099-08-05", "1988-09-04", "2023-10-03", "1978-11-02", "1890-12-01")
|
||||||
testDateFormat.parse("12.01.1980"),
|
.map(this::parseDate).collect(Collectors.toList());
|
||||||
testDateFormat.parse("11.02.1995"),
|
|
||||||
testDateFormat.parse("10.03.2045"),
|
|
||||||
testDateFormat.parse("09.04.2016"),
|
|
||||||
testDateFormat.parse("08.05.2017"),
|
|
||||||
testDateFormat.parse("07.06.1945"),
|
|
||||||
testDateFormat.parse("06.07.1998"),
|
|
||||||
testDateFormat.parse("05.08.2099"),
|
|
||||||
testDateFormat.parse("04.09.1988"),
|
|
||||||
testDateFormat.parse("03.10.2023"),
|
|
||||||
testDateFormat.parse("02.11.1978"),
|
|
||||||
testDateFormat.parse("01.12.1890"));
|
|
||||||
|
|
||||||
// Let's iterate over the test setup.
|
// Let's iterate over the test setup.
|
||||||
for (Locale locale : testMap.keySet()) {
|
final String provider = System.getProperty("java.locale.providers");
|
||||||
ExcelStyleDateFormatter formatter = new ExcelStyleDateFormatter(EXCEL_DATE_FORMAT, new DateFormatSymbols(locale));
|
final FieldPosition fp = new FieldPosition(java.text.DateFormat.MONTH_FIELD);
|
||||||
for (int i = 0; i < testDates.size(); i++) {
|
final ExcelStyleDateFormatter formatter = new ExcelStyleDateFormatter(EXCEL_DATE_FORMAT);
|
||||||
// Call the method to be tested!
|
final StringBuffer sb = new StringBuffer();
|
||||||
String result =
|
|
||||||
formatter.format(testDates.get(i),
|
for (Map.Entry<Locale,String> me : testMap.entrySet()) {
|
||||||
new StringBuffer(),
|
final Locale locale = me.getKey();
|
||||||
new FieldPosition(java.text.DateFormat.MONTH_FIELD)).toString();
|
final String expected = me.getValue();
|
||||||
//System.err.println(result + " - " + getUnicode(result.charAt(0)));
|
formatter.setDateFormatSymbols(DateFormatSymbols.getInstance(locale));
|
||||||
assertEquals("Failed for locale " + locale + ", provider: " + System.getProperty("java.locale.providers") +
|
int month = 0;
|
||||||
" and date " + testDates.get(i) + ", having: " + result,
|
for (Date d : testDates) {
|
||||||
getUnicode(testMap.get(locale).get(i).charAt(0)), getUnicode(result.charAt(0)));
|
sb.setLength(0);
|
||||||
|
String result = formatter.format(d, sb, fp).toString();
|
||||||
|
String msg = "Failed testDates for locale " + locale + ", provider: " + provider +
|
||||||
|
" and date " + d + ", having: " + result;
|
||||||
|
|
||||||
|
int actIdx = (Locale.CHINESE.equals(locale) && jreVersion >= 12) ? 1 : 0;
|
||||||
|
|
||||||
|
assertEquals(msg, expected.charAt(month), result.charAt(actIdx));
|
||||||
|
month++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<Locale, List<String>> initializeLocales() {
|
private Date parseDate(String dateStr) {
|
||||||
// Setting up the locale to be tested together with a list of asserted unicode-formatted results and put them in a map.
|
try {
|
||||||
Locale germanLocale = Locale.GERMAN;
|
return DATE_FORMAT.parse(dateStr);
|
||||||
List<String> germanResultList = Arrays.asList("\u004a", "\u0046", "\u004d", "\u0041", "\u004d",
|
} catch (ParseException e) {
|
||||||
"\u004a", "\u004a", "\u0041", "\u0053", "\u004f", "\u004e", "\u0044");
|
return new Date(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Locale russianLocale = new Locale("ru", "RU");
|
/**
|
||||||
List<String> russianResultList = Arrays.asList("\u044f", "\u0444", "\u043c", "\u0430", "\u043c",
|
* Setting up the locale to be tested together with a list of asserted
|
||||||
"\u0438", "\u0438", "\u0430", "\u0441", "\u043e", "\u043d", "\u0434");
|
* unicode-formatted results and put them in a map.
|
||||||
|
*/
|
||||||
|
private Map<Locale, String> initializeLocales() {
|
||||||
|
Map<Locale, String> testMap = new HashMap<>();
|
||||||
|
|
||||||
Locale austrianLocale = new Locale("de", "AT");
|
testMap.put(Locale.GERMAN, "JFMAMJJASOND");
|
||||||
List<String> austrianResultList = Arrays.asList("\u004a", "\u0046", "\u004d", "\u0041", "\u004d",
|
testMap.put(new Locale("de", "AT"), "JFMAMJJASOND");
|
||||||
"\u004a", "\u004a", "\u0041", "\u0053", "\u004f", "\u004e", "\u0044");
|
testMap.put(Locale.UK, "JFMAMJJASOND");
|
||||||
|
testMap.put(new Locale("en", "IN"), "JFMAMJJASOND");
|
||||||
|
testMap.put(new Locale("in", "ID"), "JFMAMJJASOND");
|
||||||
|
testMap.put(Locale.FRENCH, "jfmamjjasond");
|
||||||
|
|
||||||
Locale englishLocale = Locale.UK;
|
testMap.put(new Locale("ru", "RU"),
|
||||||
List<String> englishResultList = Arrays.asList("\u004a", "\u0046", "\u004d", "\u0041", "\u004d",
|
"\u044f\u0444\u043c\u0430\u043c\u0438\u0438\u0430\u0441\u043e\u043d\u0434");
|
||||||
"\u004a", "\u004a", "\u0041", "\u0053", "\u004f", "\u004e", "\u0044");
|
|
||||||
|
|
||||||
Locale frenchLocale = Locale.FRENCH;
|
testMap.put(Locale.CHINESE, jreVersion < 12
|
||||||
List<String> frenchResultList = Arrays.asList("\u006a", "\u0066", "\u006d", "\u0061", "\u006d",
|
? "\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u5341\u5341"
|
||||||
"\u006a", "\u006a", "\u0061", "\u0073", "\u006f", "\u006e", "\u0064");
|
: "123456789111");
|
||||||
|
|
||||||
Locale chineseLocale = Locale.CHINESE;
|
testMap.put(new Locale("tr", "TR"),
|
||||||
List<String> chineseResultList = Arrays.asList("\u4e00", "\u4e8c", "\u4e09", "\u56db", "\u4e94",
|
"\u004f\u015e\u004d\u004e\u004d\u0048\u0054\u0041\u0045\u0045\u004b\u0041");
|
||||||
"\u516d", "\u4e03", "\u516b", "\u4e5d", "\u5341", "\u5341", "\u5341");
|
|
||||||
|
|
||||||
Locale turkishLocale = new Locale("tr", "TR");
|
testMap.put(new Locale("hu", "HU"),
|
||||||
List<String> turkishResultList = Arrays.asList("\u004f", "\u015e", "\u004d", "\u004e", "\u004d",
|
"\u006a\u0066\u006d\u00e1\u006d\u006a\u006a\u0061\u0073\u006f\u006e\u0064");
|
||||||
"\u0048", "\u0054", "\u0041", "\u0045", "\u0045", "\u004b", "\u0041");
|
|
||||||
|
|
||||||
Locale hungarianLocale = new Locale("hu", "HU");
|
|
||||||
List<String> hungarianResultList = Arrays.asList("\u006a", "\u0066", "\u006d", "\u00e1", "\u006d",
|
|
||||||
"\u006a", "\u006a", "\u0061", "\u0073", "\u006f", "\u006e", "\u0064");
|
|
||||||
|
|
||||||
Locale indianLocale = new Locale("en", "IN");
|
|
||||||
List<String> indianResultList = Arrays.asList("\u004a", "\u0046", "\u004d", "\u0041", "\u004d",
|
|
||||||
"\u004a", "\u004a", "\u0041", "\u0053", "\u004f", "\u004e", "\u0044");
|
|
||||||
|
|
||||||
Locale indonesianLocale = new Locale("in", "ID");
|
|
||||||
List<String> indonesianResultList = Arrays.asList("\u004a", "\u0046", "\u004d", "\u0041", "\u004d",
|
|
||||||
"\u004a", "\u004a", "\u0041", "\u0053", "\u004f", "\u004e", "\u0044");
|
|
||||||
|
|
||||||
|
|
||||||
Map<Locale, List<String>> testMap = new HashMap<>();
|
|
||||||
testMap.put(germanLocale, germanResultList);
|
|
||||||
testMap.put(russianLocale, russianResultList);
|
|
||||||
testMap.put(austrianLocale, austrianResultList);
|
|
||||||
testMap.put(englishLocale, englishResultList);
|
|
||||||
testMap.put(frenchLocale, frenchResultList);
|
|
||||||
testMap.put(chineseLocale, chineseResultList);
|
|
||||||
testMap.put(turkishLocale, turkishResultList);
|
|
||||||
testMap.put(hungarianLocale, hungarianResultList);
|
|
||||||
testMap.put(indianLocale, indianResultList);
|
|
||||||
testMap.put(indonesianLocale, indonesianResultList);
|
|
||||||
|
|
||||||
return testMap;
|
return testMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getUnicode(char c) {
|
|
||||||
return "\\u" + Integer.toHexString(c | 0x10000).substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConstruct() {
|
public void testConstruct() {
|
||||||
new ExcelStyleDateFormatter(EXCEL_DATE_FORMAT, LocaleUtil.getUserLocale());
|
new ExcelStyleDateFormatter(EXCEL_DATE_FORMAT, LocaleUtil.getUserLocale());
|
||||||
@ -150,7 +131,7 @@ public class TestExcelStyleDateFormatter {
|
|||||||
try {
|
try {
|
||||||
LocaleUtil.setUserLocale(Locale.GERMAN);
|
LocaleUtil.setUserLocale(Locale.GERMAN);
|
||||||
String dateStr = new ExcelStyleDateFormatter(EXCEL_DATE_FORMAT).format(
|
String dateStr = new ExcelStyleDateFormatter(EXCEL_DATE_FORMAT).format(
|
||||||
new SimpleDateFormat("yyyy-MM-dd", Locale.ROOT).parse("2016-03-26"));
|
DATE_FORMAT.parse("2016-03-26"));
|
||||||
assertEquals("M", dateStr);
|
assertEquals("M", dateStr);
|
||||||
} finally {
|
} finally {
|
||||||
LocaleUtil.setUserLocale(before);
|
LocaleUtil.setUserLocale(before);
|
||||||
@ -160,7 +141,7 @@ public class TestExcelStyleDateFormatter {
|
|||||||
@Test
|
@Test
|
||||||
public void testWithPattern() throws ParseException {
|
public void testWithPattern() throws ParseException {
|
||||||
String dateStr = new ExcelStyleDateFormatter("yyyy|" + EXCEL_DATE_FORMAT + "|").format(
|
String dateStr = new ExcelStyleDateFormatter("yyyy|" + EXCEL_DATE_FORMAT + "|").format(
|
||||||
new SimpleDateFormat("yyyy-MM-dd", Locale.ROOT).parse("2016-03-26"));
|
DATE_FORMAT.parse("2016-03-26"));
|
||||||
assertEquals("2016|M|", dateStr);
|
assertEquals("2016|M|", dateStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user