]> source.dussan.org Git - poi.git/commitdiff
gather necessary .xsb for ooxml-lite jar via intercepting the calls to SchemaTypeSyst...
authorAndreas Beeker <kiwiwings@apache.org>
Mon, 28 Dec 2020 00:47:23 +0000 (00:47 +0000)
committerAndreas Beeker <kiwiwings@apache.org>
Mon, 28 Dec 2020 00:47:23 +0000 (00:47 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1884850 13f79535-47bb-0310-9956-ffa450edef68

build.xml
src/multimodule/ooxml-lite-agent/java9/module-info.class
src/multimodule/ooxml-lite-agent/java9/module-info.java
src/ooxml/testcases/org/apache/poi/ooxml/lite/OOXMLLiteAgent.java

index 836e149ffb4384b8ea30fb7d43cb70abcb2a4997..221c8678e882585d7d52fddfdb9b4a783bf0eddc 100644 (file)
--- a/build.xml
+++ b/build.xml
@@ -157,7 +157,7 @@ under the License.
     <property name="ooxml.testokfile" location="build/ooxml-testokfile.txt"/>
 
     <property name="ooxml.lite.agent" location="lib/ooxml-tests/ooxml-lite-agent.jar"/>
-    <property name="ooxml.lite.report" location="build/ooxml-lite-report.txt"/>
+    <property name="ooxml.lite.report" location="build/ooxml-lite-report"/>
     <property name="ooxml.lite.jar" location="build/dist/maven/poi-ooxml-lite/poi-ooxml-lite-${version.id}.jar"/>
     <property name="ooxml.lite.includes" value="^(com/microsoft/schemas|org/(etsi|openxmlformats|w3/)|org/apache/poi/schemas)"/>
 
@@ -1157,6 +1157,7 @@ under the License.
                destdir="${basedir}/src/multimodule/ooxml-lite-agent/java9"
                includeantruntime="false"
                fork="true"
+               modulepath="${basedir}/lib/main-tests"
                unless:true="${isJava8}">
             <compilerarg line="--patch-module org.apache.poi.ooxml_lite=${ooxml.output.test.dir}"/>
         </javac>
@@ -1168,6 +1169,7 @@ under the License.
                 <attribute name="Multi-Release" value="true"/>
                 <attribute name="Automatic-Module-Name" value="org.apache.poi.ooxml_lite"/>
                 <attribute name="Premain-Class" value="org.apache.poi.ooxml.lite.OOXMLLiteAgent"/>
+                <!-- attribute name="Can-Retransform-Classes" value="true"/ -->
             </manifest>
         </jar>
     </target>
@@ -1711,7 +1713,7 @@ under the License.
         <echo message="Create ooxml-lite schemas"/>
         <local name="lite.exports"/>
         <loadresource property="lite.exports">
-            <file file="${ooxml.lite.report}"/>
+            <file file="${ooxml.lite.report}.clazz"/>
             <filterchain>
                 <tokenfilter>
                     <replaceregex pattern="[/\\][^/\\]+$" replace=""/>
@@ -1750,7 +1752,7 @@ under the License.
             </modulepath>
         </javac>
 
-        <copy file="${ooxml.lite.report}" tofile="build/ooxml-lite-classes.txt" overwrite="true">
+        <copy file="${ooxml.lite.report}.clazz" tofile="${ooxml.lite.report}.clazz2" overwrite="true">
             <filterchain>
                 <tokenfilter>
                     <replaceregex pattern="(.*)" replace="\1.class${line.separator}\1$*.class "/>
@@ -1758,62 +1760,22 @@ under the License.
             </filterchain>
         </copy>
 
-        <local name="ooxml.lite.xsbs"/>
-        <loadresource property="ooxml.lite.xsbs">
-            <file file="${ooxml.lite.report}"/>
+        <copy file="${ooxml.lite.report}.xsb" tofile="${ooxml.lite.report}.xsb2" overwrite="true">
             <filterchain>
-                <linecontains negate="true" matchany="true">
-                    <contains value="$"/>
-                    <contains value="TypeSystemHolder"/>
-                </linecontains>
-                <suffixlines suffix=".java"/>
+                <prefixlines prefix="org/apache/poi/schemas/ooxml/system/ooxml/"/>
+                <suffixlines suffix=".xsb"/>
             </filterchain>
-        </loadresource>
-
-        <concat dest="build/ooxml-lite-classes.txt" append="true">
-            <filelist dir="build/xmlbean-sources" files="${ooxml.lite.xsbs}"/>
-            <filterchain>
-                <linecontains>
-                    <contains value="resolveHandle"/>
-                </linecontains>
-                <replaceregex pattern='.*"([^"]+)".*' replace="org/apache/poi/schemas/ooxml/system/ooxml/\1.xsb"/>
-            </filterchain>
-        </concat>
-
-        <!-- the following xsb files aren't detected, i.e. not directly loaded by XmlBeans interface classes -->
-        <echo file="build/ooxml-lite-classes.txt" append="true">
-org/apache/poi/schemas/ooxml/system/ooxml/index.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/picelement.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/groupelement.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/group7d3fdoctype.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/shapelayoutelement.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/shapetypeelement.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/shapetypeb89bdoctype.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/shapeelement.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/shapeaee1doctype.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/tblelement.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/tbleb1bdoctype.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/relationshipreferenceelement.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/qualifyingpropertieselement.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/oleobjelement.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/oleobj8482doctype.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/stcellspans60f6type.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/stcellspanf3a5type.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/alternatecontentelement.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/chartelement.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/chartf85cdoctype.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/rectelement.xsb
-org/apache/poi/schemas/ooxml/system/ooxml/rectaf36doctype.xsb
-        </echo>
+        </copy>
 
         <mkdir dir="build/dist/maven/poi-ooxml-lite"/>
 
         <jar destfile="${ooxml.lite.jar}" duplicate="preserve">
             <zipfileset dir="${basedir}/src/multimodule/ooxml-lite/java9" prefix="META-INF/versions/9" excludes="*.java"/>
             <zipfileset src="${ooxml.xsds.jar}">
-                <patternset includesfile="build/ooxml-lite-classes.txt">
+                <patternset includesfile="${ooxml.lite.report}.clazz2">
                     <include name="org/apache/poi/schemas/ooxml/element/**/*.xsb"/>
                 </patternset>
+                <patternset includesfile="${ooxml.lite.report}.xsb2"/>
             </zipfileset>
             <zipfileset dir="src/multimodule/ooxml-full/java9" prefix="META-INF/versions/9" excludes="*.java"/>
             <manifest>
index 45ff2cad3857a66faab61ae52ab43860ab9fbab5..51e4e32994f998f4004e7511b1da551cc0fdc8d8 100644 (file)
Binary files a/src/multimodule/ooxml-lite-agent/java9/module-info.class and b/src/multimodule/ooxml-lite-agent/java9/module-info.class differ
index 04058f1cfc872ecefa4a8def0febabc10c49f99a..85184ca2b221380a78325a246fdda3a8596c0651 100644 (file)
@@ -17,6 +17,7 @@
 
 module org.apache.poi.ooxml_lite {
     requires java.instrument;
+    requires static net.bytebuddy.agent;
 
     exports org.apache.poi.ooxml.lite;
 }
\ No newline at end of file
index 21c7f28786c6feed41d09c7a83ad49eea29e156b..b95e9df7e9ef67ca79046799dc0c5fd185343c19 100644 (file)
@@ -17,6 +17,8 @@
 
 package org.apache.poi.ooxml.lite;
 
+import static net.bytebuddy.matcher.ElementMatchers.named;
+
 import java.io.IOException;
 import java.lang.instrument.ClassFileTransformer;
 import java.lang.instrument.Instrumentation;
@@ -31,48 +33,108 @@ import java.util.Set;
 import java.util.regex.Pattern;
 import java.util.stream.Stream;
 
+import net.bytebuddy.agent.builder.AgentBuilder;
+import net.bytebuddy.implementation.MethodDelegation;
+import net.bytebuddy.implementation.SuperMethodCall;
+import net.bytebuddy.matcher.ElementMatchers;
+import org.apache.xmlbeans.impl.schema.SchemaTypeSystemImpl;
+
 /**
  * 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 static void premain(String agentArgs, Instrumentation inst) throws IOException {
+        String[] args = (agentArgs == null ? "" : agentArgs).split("\\|", 2);
+        String logBase = args.length >= 1 ? args[0] : "ooxml-lite-report";
 
-        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/.*");
+        XsbLogger.load(logBase+".xsb");
 
-            try {
-                if (Files.exists(path)) {
-                    try (Stream<String> stream = Files.lines(path)) {
-                        stream.forEach((s) -> fileHashes.add(s.hashCode()));
-                    }
-                } else {
-                    Files.createFile(path);
+        ClazzLogger log = new ClazzLogger();
+        log.load(logBase+".clazz");
+        log.setPattern(args.length >= 2 ? args[1] : ".*/schemas/.*");
+        inst.addTransformer(log);
+
+        new AgentBuilder.Default()
+        // .with(AgentBuilder.Listener.StreamWriting.toSystemOut())
+            .type(named("org.apache.xmlbeans.impl.schema.SchemaTypeSystemImpl$XsbReader"))
+            .transform((builder, type, cl, m) ->
+                builder
+                .constructor(ElementMatchers.any())
+                .intercept(MethodDelegation.to(XsbLogger.class).andThen(SuperMethodCall.INSTANCE))
+            )
+            .installOn(inst);
+    }
+
+    /**
+     * This logger intercepts the loading of XmlBeans .xsb
+     *
+     * when ran in the ant junitlauncher, it's not possible to have the interceptor methods as
+     * instance method of ClazzLogger. the junit test will fail ... though it works ok in IntelliJ
+     * probably because of classpath vs. modulepath instantiation
+     */
+    public static class XsbLogger {
+        private static Path logPath;
+        private static final Set<Integer> hashes = new HashSet<>();
+
+        static void load(String path) throws IOException {
+            logPath = Paths.get(path);
+            if (Files.exists(logPath)) {
+                try (Stream<String> stream = Files.lines(logPath)) {
+                    stream.forEach((s) -> hashes.add(s.hashCode()));
                 }
-            } 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) {
+        // SchemaTypeSystemImpl.XsbReader::new is delegated to here - method name doesn't matter
+        public static void loadXsb(SchemaTypeSystemImpl parent, String handle) {
+            write(logPath, handle, hashes);
+        }
+
+        public static void loadXsb(SchemaTypeSystemImpl parent, String handle, int filetype) {
+            loadXsb(parent, handle);
+        }
+    }
+
+    /**
+     * This logger is used to log the used XmlBeans classes
+     */
+    public static class ClazzLogger implements ClassFileTransformer {
+        Path logPath;
+        Pattern includes;
+        final Set<Integer> hashes = new HashSet<>();
+
+        public void setPattern(String regex) {
+            includes = Pattern.compile(regex);
+        }
+
+        public void load(String path) throws IOException {
+            this.logPath = Paths.get(path);
+            if (Files.exists(this.logPath)) {
+                try (Stream<String> stream = Files.lines(this.logPath)) {
+                    stream.forEach((s) -> hashes.add(s.hashCode()));
                 }
             }
+        }
+
+        public byte[] transform(ClassLoader loader, String className, Class redefiningClass, ProtectionDomain domain, byte[] bytes) {
+            if (logPath != null && className != null && includes.matcher(className).find()) {
+                write(logPath, className, hashes);
+            }
             return bytes;
         }
     }
 
-    public static void premain(String agentArgs, Instrumentation inst) {
-        inst.addTransformer(new LoggingTransformer(agentArgs));
+
+    static void write(Path path, String item, Set<Integer> hashes) {
+        if (!hashes.contains(item.hashCode())) {
+            try {
+                // TODO: check if this is atomic ... as transform() is probably called synchronized, it doesn't matter anyway
+                Files.write(path, (item+"\n").getBytes(StandardCharsets.ISO_8859_1), StandardOpenOption.CREATE, StandardOpenOption.APPEND);
+                hashes.add(item.hashCode());
+            } catch (IOException ignroed) {
+            }
+        }
     }
 }