From 07ba96f02340d4674714bf445f4c23bd5664524d Mon Sep 17 00:00:00 2001 From: Andreas Beeker Date: Mon, 28 Dec 2020 00:47:23 +0000 Subject: [PATCH] gather necessary .xsb for ooxml-lite jar via intercepting the calls to SchemaTypeSystemImpl.XsbReader git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1884850 13f79535-47bb-0310-9956-ffa450edef68 --- build.xml | 60 ++-------- .../ooxml-lite-agent/java9/module-info.class | Bin 188 -> 219 bytes .../ooxml-lite-agent/java9/module-info.java | 1 + .../apache/poi/ooxml/lite/OOXMLLiteAgent.java | 112 ++++++++++++++---- 4 files changed, 99 insertions(+), 74 deletions(-) diff --git a/build.xml b/build.xml index 836e149ffb..221c8678e8 100644 --- a/build.xml +++ b/build.xml @@ -157,7 +157,7 @@ under the License. - + @@ -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}"> @@ -1168,6 +1169,7 @@ under the License. + @@ -1711,7 +1713,7 @@ under the License. - + @@ -1750,7 +1752,7 @@ under the License. - + @@ -1758,62 +1760,22 @@ under the License. - - - + - - - - - + + - - - - - - - - - - - - - - -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 - + - + + diff --git a/src/multimodule/ooxml-lite-agent/java9/module-info.class b/src/multimodule/ooxml-lite-agent/java9/module-info.class index 45ff2cad3857a66faab61ae52ab43860ab9fbab5..51e4e32994f998f4004e7511b1da551cc0fdc8d8 100644 GIT binary patch delta 161 zcmdnPc$-oE)W2Q(7#J8#8Ti;4m>3zjbMsS5b5eCP^V0Ge8Q6TmJYfdbi3Tzb!VK(; z44hesWr=!8iN&eH44jM%{9tZoUU5lLX>Mv>i7*2 qLWF^LVwScpGte##1{NU6z`)GF)&Qb8Km-F9g9DIcWZ(gDAOHXrVIg?{ literal 188 zcmXAjIS#@w5JkTOB!nPQn1+@fyW$v}0U0o0lAbDW%N-iFA3_0cnWqB uec)AMWqaQZMp~auo=qN1o=hIi5g_4@oGCj1 diff --git a/src/multimodule/ooxml-lite-agent/java9/module-info.java b/src/multimodule/ooxml-lite-agent/java9/module-info.java index 04058f1cfc..85184ca2b2 100644 --- a/src/multimodule/ooxml-lite-agent/java9/module-info.java +++ b/src/multimodule/ooxml-lite-agent/java9/module-info.java @@ -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 diff --git a/src/ooxml/testcases/org/apache/poi/ooxml/lite/OOXMLLiteAgent.java b/src/ooxml/testcases/org/apache/poi/ooxml/lite/OOXMLLiteAgent.java index 21c7f28786..b95e9df7e9 100644 --- a/src/ooxml/testcases/org/apache/poi/ooxml/lite/OOXMLLiteAgent.java +++ b/src/ooxml/testcases/org/apache/poi/ooxml/lite/OOXMLLiteAgent.java @@ -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 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 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 hashes = new HashSet<>(); + + static void load(String path) throws IOException { + logPath = Paths.get(path); + if (Files.exists(logPath)) { + try (Stream 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 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 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 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) { + } + } } } -- 2.39.5