]> source.dussan.org Git - poi.git/commitdiff
#62921 - Provide OOXMLLite alternative for Java 12+
authorAndreas Beeker <kiwiwings@apache.org>
Sun, 18 Nov 2018 00:01:40 +0000 (00:01 +0000)
committerAndreas Beeker <kiwiwings@apache.org>
Sun, 18 Nov 2018 00:01:40 +0000 (00:01 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1846809 13f79535-47bb-0310-9956-ffa450edef68

build.xml
src/ooxml/testcases/org/apache/poi/ooxml/util/OOXMLLite.java [deleted file]
src/ooxml/testcases/org/apache/poi/ooxml/util/OOXMLLiteAgent.java [new file with mode: 0644]
src/ooxml/testcases/org/apache/poi/ss/format/TestCellFormatPart.java
src/scratchpad/testcases/org/apache/poi/hmef/TestAttachments.java
src/scratchpad/testcases/org/apache/poi/hmef/attribute/TestMAPIAttributes.java
src/scratchpad/testcases/org/apache/poi/hmef/attribute/TestTNEFAttributes.java
src/testcases/org/apache/poi/ss/usermodel/TestExcelStyleDateFormatter.java

index d15b45b74b2168fbb0e2af2042ebdbc0b1a236a7..89f0423e78d31e3c1b2344bddc54aba77d42e0a7 100644 (file)
--- a/build.xml
+++ b/build.xml
@@ -130,8 +130,12 @@ under the License.
     <property name="ooxml.output.dir" location="build/ooxml-classes"/>
     <property name="ooxml.output.test.dir" location="build/ooxml-test-classes"/>
     <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: -->
     <property name="integration.src.test" location="src/integrationtest"/>
@@ -397,7 +401,8 @@ under the License.
 
     <path id="ooxml-lite.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.test.dir}"/>
         <pathelement location="${main.output.test.dir}"/>
@@ -1015,8 +1020,6 @@ under the License.
             compile-scratchpad, compile-examples, compile-excelant"
             description="Compiles the POI main classes, scratchpad and examples"/>
 
-    <target name="compile-all" depends="compile,compile-ooxml-lite"/>
-
     <target name="compile-main" depends="init">
         <!-- compile the sources -->
         <javac target="${jdk.version.class}"
@@ -1338,7 +1341,7 @@ under the License.
     <!-- Section: test (execute junit tests on test suites) -->
     <target name="test" depends="compile,jacocotask,test-main,test-scratchpad,test-ooxml,test-excelant"
             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"/>
 
     <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">
                     <classfiles>
                         <fileset dir="${ooxml.output.dir}"/>
-                        <!-- there are no actual POI classes in build/ooxml-lite-classes, only generated code...
-                        <fileset dir="${ooxml.lite.output.dir}"/>
-                        -->
+                        <!-- there are no actual POI classes in build/ooxml-lite-classes, only generated code... -->
                     </classfiles>
                     <sourcefiles encoding="UTF-8">
                         <fileset dir="${ooxml.src}"/>
@@ -1564,6 +1565,7 @@ under the License.
                   <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}" />
@@ -1598,6 +1600,7 @@ under the License.
                   </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}" />
@@ -1620,7 +1623,7 @@ under the License.
         </sequential>
     </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">
         <ooxml-test-runner classpath="test.ooxml.classpath" type="ooxml"/>
         <delete file="${ooxml.testokfile}"/>
@@ -1638,7 +1641,7 @@ under the License.
         </uptodate>
     </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">
         <propertyreset name="org.apache.poi.util.POILogger" value="org.apache.poi.util.CommonsLogger"/>
         <delete dir="build" includes="test-integration.log*"/>
@@ -1650,6 +1653,7 @@ under the License.
                 <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}" />
@@ -1677,57 +1681,28 @@ under the License.
         <echo file="${integration.testokfile}" append="false" message="testok"/>
     </target>
 
-    <!-- Section: test-ooxml-lite -->
-    <target name="-compile-ooxml-lite-check">
-        <uptodate property="ooxml.lite.test.notRequired" targetfile="${ooxml.lite.testokfile}">
-            <srcfiles dir="${ooxml.src}"/>
-            <srcfiles dir="${ooxml.src.test}"/>
-            <srcfiles file="${ooxml.xsds.jar}"/>
-            <srcfiles file="${ooxml.security.jar}"/>
-        </uptodate>
-    </target>
+    <!-- the ooxml lite agent collects referenced schema files while other junit tests are run, -->
+    <!-- therefore its best to compile the ooxml lite jar after all usual tests are done -->
+    <target name="compile-ooxml-lite" depends="compile-ooxml,-ooxml-lite-agent,test-ooxml">
+        <echo message="Create ooxml-lite schemas"/>
 
-    <target name="compile-ooxml-lite" depends="-compile-ooxml-lite-check,compile-ooxml"
-            unless="ooxml.lite.test.notRequired">
-        <delete file="${ooxml.lite.testokfile}"/>
-        <echo message="Running ooxml-lite generator"/>
+        <copy file="${ooxml.lite.report}" tofile="${ooxml.lite.report}-pat" overwrite="true"/>
+        <replaceregexp file="${ooxml.lite.report}-pat" byline="true" match="(.*)" replace="\1.class${line.separator}\1$*.class"/>
 
-        <property name="ooxml.lite-merged.dir" location="build/ooxml-lite-merged"/>
-        <mkdir dir="${ooxml.lite-merged.dir}"/>
+        <patternset id="xsbfiles">
+            <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">
-            <zipfileset includes="**/*" src="${ooxml.xsds.jar}"/>
-            <zipfileset includes="**/*" src="${ooxml.security.jar}"/>
+        <jar destfile="${ooxml.lite.jar}" duplicate="preserve">
+            <zipfileset src="${ooxml.xsds.jar}">
+                <patternset refid="xsbfiles"/>
+            </zipfileset>
+            <zipfileset src="${ooxml.security.jar}">
+                <patternset refid="xsbfiles"/>
+            </zipfileset>
         </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 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"/>
     </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 -->
     <target name="-test-excelant-check">
         <uptodate property="excelant.test.notRequired" targetfile="${excelant.testokfile}">
@@ -1953,11 +1937,11 @@ under the License.
     </target>
 
     <macrodef name="maven-jar">
-        <attribute name="dir"/>
+        <attribute name="src"/>
         <sequential>
             <local name="destfile"/>
             <pathconvert property="destfile" targetos="unix">
-                <path><pathelement path="@{dir}"/></path>
+                <path><pathelement path="@{src}"/></path>
                 <mapper>
                     <chainedmapper>
                         <filtermapper>
@@ -1971,33 +1955,39 @@ under the License.
                     </chainedmapper>
                 </mapper>
             </pathconvert>
+            <local name="isjar"/>
+            <condition property="isjar">
+                <contains string="@{src}" substring=".jar"/>
+            </condition>
+
             <jar destfile="build/dist/maven/${destfile}.jar"
                  manifest="build/poi-manifest.mf">
-                <fileset dir="@{dir}"/>
+                <fileset dir="@{src}" unless:true="${isjar}"/>
+                <zipfileset src="@{src}" if:true="${isjar}"/>
                 <metainf dir="legal/"/>
             </jar>
         </sequential>
     </macrodef>
 
-    <target name="jar" depends="compile-all, compile-version, -manifest" description="Creates jar files for distribution">
-        <maven-jar dir="${main.output.dir}"/>
-        <maven-jar dir="${scratchpad.output.dir}"/>
-        <maven-jar dir="${ooxml.output.dir}"/>
-        <maven-jar dir="${examples.output.dir}"/>
-        <maven-jar dir="${excelant.output.dir}"/>
-        <maven-jar dir="${ooxml.lite.output.dir}"/>
+    <target name="jar" depends="compile, compile-version, -manifest" description="Creates jar files for distribution">
+        <maven-jar src="${main.output.dir}"/>
+        <maven-jar src="${scratchpad.output.dir}"/>
+        <maven-jar src="${ooxml.output.dir}"/>
+        <maven-jar src="${examples.output.dir}"/>
+        <maven-jar src="${excelant.output.dir}"/>
+        <maven-jar src="${ooxml.lite.jar}"/>
     </target>
 
-    <target name="jar-src" depends="compile-all, compile-version, -manifest" description="Sources for Maven">
-        <maven-jar dir="${main.src}"/>
-        <maven-jar dir="${scratchpad.src}"/>
-        <maven-jar dir="${ooxml.src}"/>
-        <maven-jar dir="${examples.src}"/>
-        <maven-jar dir="${excelant.src}"/>
+    <target name="jar-src" depends="compile, compile-version, -manifest" description="Sources for Maven">
+        <maven-jar src="${main.src}"/>
+        <maven-jar src="${scratchpad.src}"/>
+        <maven-jar src="${ooxml.src}"/>
+        <maven-jar src="${examples.src}"/>
+        <maven-jar src="${excelant.src}"/>
     </target>
 
     <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 name="-do-jar-check-javadocs-package-list">
@@ -2112,6 +2102,7 @@ under the License.
                       lib/**,
                       bin/**,
                       out/**,
+                      tmp/**,
                       sonar/**/target/**,
                       sonar/*/src/**,
                       compile-lib/**,
@@ -2167,14 +2158,12 @@ under the License.
        </mvn:mvn>
     </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">
     </target>
 
     <!-- continuous integration targets -->
-    <target name="gump" depends="compile-all, test-all, jar"
-        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"
+    <target name="jenkins" depends="compile, test-all, 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."/>
 
     <available property="maven.ant.tasks.present" classname="org.apache.maven.artifact.ant.Pom"/>
diff --git a/src/ooxml/testcases/org/apache/poi/ooxml/util/OOXMLLite.java b/src/ooxml/testcases/org/apache/poi/ooxml/util/OOXMLLite.java
deleted file mode 100644 (file)
index 450f958..0000000
+++ /dev/null
@@ -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);
-        }
-    }
-}
diff --git a/src/ooxml/testcases/org/apache/poi/ooxml/util/OOXMLLiteAgent.java b/src/ooxml/testcases/org/apache/poi/ooxml/util/OOXMLLiteAgent.java
new file mode 100644 (file)
index 0000000..48c9240
--- /dev/null
@@ -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));
+    }
+}
index 583fa8b851dc94c5b14fec7075db13abde46237c..fd1c8d8a1001e1ce23060fda3a58e0a22da6a1b4 100644 (file)
@@ -41,7 +41,7 @@ public class TestCellFormatPart extends CellFormatTestBase {
     @BeforeClass
     public static void setLocale() {
         userLocale = LocaleUtil.getUserLocale();
-        LocaleUtil.setUserLocale(Locale.ROOT);
+        LocaleUtil.setUserLocale(Locale.UK);
     }
     
     @AfterClass
index 18f59725bbb20e053185e3387e6a9b46e8a55beb..87655cb3aef5350772046e653d0b4ca4162431fd 100644 (file)
@@ -18,6 +18,7 @@
 package org.apache.poi.hmef;
 
 import java.text.DateFormat;
+import java.text.SimpleDateFormat;
 import java.util.List;
 import java.util.Locale;
 
@@ -83,9 +84,7 @@ public final class TestAttachments extends HMEFTest {
       List<Attachment> attachments = quick.getAttachments();
       
       // Pick a predictable date format + timezone
-      DateFormat fmt = DateFormat.getDateTimeInstance(
-            DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK
-      );
+      DateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss", Locale.UK);
       fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
       
       // They should all have the same date on them
index f8543948161df111d1853710f66070e61b542899..7fcad02042d743acd61b5455e8b7b4cfff2945b2 100644 (file)
@@ -20,6 +20,7 @@ package org.apache.poi.hmef.attribute;
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.text.DateFormat;
+import java.text.SimpleDateFormat;
 import java.util.Locale;
 
 import org.apache.poi.POIDataSamples;
@@ -159,9 +160,7 @@ protected void tearDown() throws Exception {
       assertEquals(MAPIDateAttribute.class, attr.getClass());
       
       MAPIDateAttribute date = (MAPIDateAttribute)attr;
-      DateFormat fmt = DateFormat.getDateTimeInstance(
-            DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK
-      );
+      DateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss", Locale.UK);
       fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
       assertEquals("15-Dec-2010 14:46:31", fmt.format(date.getDate()));
       
index cd13b94b39ec91869633189f2466d3d0aca059c9..04004fae23c82c4659bdb2db97c830e9d95627bb 100644 (file)
@@ -19,6 +19,7 @@ package org.apache.poi.hmef.attribute;
 
 import java.io.ByteArrayInputStream;
 import java.text.DateFormat;
+import java.text.SimpleDateFormat;
 import java.util.Locale;
 
 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
       // Pick a predictable format + location + timezone
       TNEFDateAttribute date = (TNEFDateAttribute)attr;
-      DateFormat fmt = DateFormat.getDateTimeInstance(
-            DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.UK
-      );
+      DateFormat fmt = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss", Locale.UK);
       fmt.setTimeZone(LocaleUtil.TIMEZONE_UTC);
       assertEquals("28-Apr-2010 12:40:56", fmt.format(date.getDate()));
        }
index f4e61801a5ff9c6b4cf093170c0cbe29349a067d..9d64f3a8a09cc56f7b6501518edf4f5e6d590c71 100644 (file)
@@ -23,119 +23,100 @@ import java.text.DateFormatSymbols;
 import java.text.FieldPosition;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
-import java.util.Arrays;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import org.apache.poi.util.LocaleUtil;
 import org.junit.Test;
 
 public class TestExcelStyleDateFormatter {
     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
      */
     @Test
-    public void test60369() throws ParseException {
-        Map<Locale, List<String>> testMap = initializeLocales();
+    public void test60369() {
+        Map<Locale, String> testMap = initializeLocales();
 
         // We have to set up dates as well.
-        SimpleDateFormat testDateFormat = new SimpleDateFormat("dd.MM.yyyy", Locale.ROOT);
-        List<Date> testDates = Arrays.asList(
-                testDateFormat.parse("12.01.1980"),
-                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"));
+        List<Date> testDates = Stream.of("1980-01-12", "1995-02-11", "2045-03-10", "2016-04-09", "2017-05-08",
+            "1945-06-07", "1998-07-06", "2099-08-05", "1988-09-04", "2023-10-03", "1978-11-02", "1890-12-01")
+            .map(this::parseDate).collect(Collectors.toList());
 
         // Let's iterate over the test setup.
-        for (Locale locale : testMap.keySet()) {
-            ExcelStyleDateFormatter formatter = new ExcelStyleDateFormatter(EXCEL_DATE_FORMAT, new DateFormatSymbols(locale));
-            for (int i = 0; i < testDates.size(); i++) {
-                // Call the method to be tested!
-                String result =
-                        formatter.format(testDates.get(i),
-                                new StringBuffer(),
-                                new FieldPosition(java.text.DateFormat.MONTH_FIELD)).toString();
-                //System.err.println(result +  " - " + getUnicode(result.charAt(0)));
-                assertEquals("Failed for locale " + locale + ", provider: " + System.getProperty("java.locale.providers") +
-                        " and date " + testDates.get(i) + ", having: " + result,
-                        getUnicode(testMap.get(locale).get(i).charAt(0)), getUnicode(result.charAt(0)));
+        final String provider = System.getProperty("java.locale.providers");
+        final FieldPosition fp = new FieldPosition(java.text.DateFormat.MONTH_FIELD);
+        final ExcelStyleDateFormatter formatter = new ExcelStyleDateFormatter(EXCEL_DATE_FORMAT);
+        final StringBuffer sb = new StringBuffer();
+
+        for (Map.Entry<Locale,String> me : testMap.entrySet()) {
+            final Locale locale = me.getKey();
+            final String expected = me.getValue();
+            formatter.setDateFormatSymbols(DateFormatSymbols.getInstance(locale));
+            int month = 0;
+            for (Date d : testDates) {
+                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() {
-        // Setting up the locale to be tested together with a list of asserted unicode-formatted results and put them in a map.
-        Locale germanLocale = Locale.GERMAN;
-        List<String> germanResultList = Arrays.asList("\u004a", "\u0046", "\u004d", "\u0041", "\u004d",
-                "\u004a", "\u004a", "\u0041", "\u0053", "\u004f", "\u004e", "\u0044");
-
-        Locale russianLocale = new Locale("ru", "RU");
-        List<String> russianResultList = Arrays.asList("\u044f", "\u0444", "\u043c", "\u0430", "\u043c",
-                "\u0438", "\u0438", "\u0430", "\u0441", "\u043e", "\u043d", "\u0434");
-
-        Locale austrianLocale = new Locale("de", "AT");
-        List<String> austrianResultList = Arrays.asList("\u004a", "\u0046", "\u004d", "\u0041", "\u004d",
-                "\u004a", "\u004a", "\u0041", "\u0053", "\u004f", "\u004e", "\u0044");
-
-        Locale englishLocale = Locale.UK;
-        List<String> englishResultList = Arrays.asList("\u004a", "\u0046", "\u004d", "\u0041", "\u004d",
-                "\u004a", "\u004a", "\u0041", "\u0053", "\u004f", "\u004e", "\u0044");
-
-        Locale frenchLocale = Locale.FRENCH;
-        List<String> frenchResultList = Arrays.asList("\u006a", "\u0066", "\u006d", "\u0061", "\u006d",
-                "\u006a", "\u006a", "\u0061", "\u0073", "\u006f", "\u006e", "\u0064");
-
-        Locale chineseLocale = Locale.CHINESE;
-        List<String> chineseResultList = Arrays.asList("\u4e00", "\u4e8c", "\u4e09", "\u56db", "\u4e94",
-                "\u516d", "\u4e03", "\u516b", "\u4e5d", "\u5341", "\u5341", "\u5341");
-
-        Locale turkishLocale = new Locale("tr", "TR");
-        List<String> turkishResultList = Arrays.asList("\u004f", "\u015e", "\u004d", "\u004e", "\u004d",
-                "\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;
+    private Date parseDate(String dateStr) {
+        try {
+            return DATE_FORMAT.parse(dateStr);
+        } catch (ParseException e) {
+            return new Date(0);
+        }
     }
 
-    private String getUnicode(char c) {
-        return "\\u" + Integer.toHexString(c | 0x10000).substring(1);
+    /**
+     * Setting up the locale to be tested together with a list of asserted
+     * unicode-formatted results and put them in a map.
+     */
+    private Map<Locale, String> initializeLocales() {
+        Map<Locale, String> testMap = new HashMap<>();
+
+        testMap.put(Locale.GERMAN, "JFMAMJJASOND");
+        testMap.put(new Locale("de", "AT"), "JFMAMJJASOND");
+        testMap.put(Locale.UK, "JFMAMJJASOND");
+        testMap.put(new Locale("en", "IN"), "JFMAMJJASOND");
+        testMap.put(new Locale("in", "ID"), "JFMAMJJASOND");
+        testMap.put(Locale.FRENCH, "jfmamjjasond");
+
+        testMap.put(new Locale("ru", "RU"),
+            "\u044f\u0444\u043c\u0430\u043c\u0438\u0438\u0430\u0441\u043e\u043d\u0434");
+
+        testMap.put(Locale.CHINESE, jreVersion < 12
+            ? "\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341\u5341\u5341"
+            : "123456789111");
+
+        testMap.put(new Locale("tr", "TR"),
+            "\u004f\u015e\u004d\u004e\u004d\u0048\u0054\u0041\u0045\u0045\u004b\u0041");
+
+        testMap.put(new Locale("hu", "HU"),
+            "\u006a\u0066\u006d\u00e1\u006d\u006a\u006a\u0061\u0073\u006f\u006e\u0064");
+
+        return testMap;
     }
 
     @Test
@@ -150,7 +131,7 @@ public class TestExcelStyleDateFormatter {
         try {
             LocaleUtil.setUserLocale(Locale.GERMAN);
             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);
         } finally {
             LocaleUtil.setUserLocale(before);
@@ -160,7 +141,7 @@ public class TestExcelStyleDateFormatter {
     @Test
     public void testWithPattern() throws ParseException {
         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);
     }
 }