From cb03495d36fd0cb32e41469c0b34ca73f371baee Mon Sep 17 00:00:00 2001 From: Andreas Beeker Date: Sat, 8 Oct 2016 17:07:15 +0000 Subject: [PATCH] Bug 60226 - ClassLoader workaround for OSGI when processing OOXML files git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1763922 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/org/apache/poi/POIXMLTypeLoader.java | 42 +++++++++++--- .../apache/poi/xslf/usermodel/XSLFTable.java | 58 ++++++++++--------- .../org/apache/poi/TestPOIXMLDocument.java | 37 ++++++++++++ 3 files changed, 103 insertions(+), 34 deletions(-) diff --git a/src/ooxml/java/org/apache/poi/POIXMLTypeLoader.java b/src/ooxml/java/org/apache/poi/POIXMLTypeLoader.java index b703d73d8..eeed5f7c8 100644 --- a/src/ooxml/java/org/apache/poi/POIXMLTypeLoader.java +++ b/src/ooxml/java/org/apache/poi/POIXMLTypeLoader.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.io.StringReader; +import java.lang.ref.WeakReference; import java.net.URL; import java.util.Collections; import java.util.HashMap; @@ -32,6 +33,7 @@ import javax.xml.stream.XMLStreamReader; import org.apache.poi.util.DocumentHelper; import org.apache.xmlbeans.SchemaType; +import org.apache.xmlbeans.SchemaTypeLoader; import org.apache.xmlbeans.XmlBeans; import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlObject; @@ -46,6 +48,8 @@ import org.xml.sax.SAXException; @SuppressWarnings("deprecation") public class POIXMLTypeLoader { + private static ThreadLocal classLoader = new ThreadLocal(); + public static final XmlOptions DEFAULT_XML_OPTIONS; static { DEFAULT_XML_OPTIONS = new XmlOptions(); @@ -80,8 +84,32 @@ public class POIXMLTypeLoader { return options == null ? DEFAULT_XML_OPTIONS : options; } + /** + * Sets the {@link ClassLoader} which is used, when XmlBeans are dynamically instantiated - + * opposed to being loaded by the factory class which is accompanied by each generated XmlBeans interface. + *

+ * This is especially necessary in a context which doesn't guarantee that the current (thread) context + * cassloader has access to all XmlBeans schema definitions (*.xsb) - which is typically in OSGI the case. + *

+ * The classloader will be only set for the current thread in a {@link ThreadLocal}. Although the + * ThreadLocal is implemented via a {@link WeakReference}, it's good style to {@code null} the classloader + * when the user code is finalized. + * + * @param cl the classloader to be used when XmlBeans classes and definitions are looked up + */ + public static void setClassLoader(ClassLoader cl) { + classLoader.set(cl); + } + + private static SchemaTypeLoader getTypeLoader() { + ClassLoader cl = classLoader.get(); + return (cl == null) + ? XmlBeans.getContextTypeLoader() + : XmlBeans.typeLoaderForClassLoader(cl); + } + public static XmlObject newInstance(SchemaType type, XmlOptions options) { - return XmlBeans.getContextTypeLoader().newInstance(type, getXmlOptions(options)); + return getTypeLoader().newInstance(type, getXmlOptions(options)); } public static XmlObject parse(String xmlText, SchemaType type, XmlOptions options) throws XmlException { @@ -113,34 +141,34 @@ public class POIXMLTypeLoader { public static XmlObject parse(InputStream jiois, SchemaType type, XmlOptions options) throws XmlException, IOException { try { Document doc = DocumentHelper.readDocument(jiois); - return XmlBeans.getContextTypeLoader().parse(doc.getDocumentElement(), type, getXmlOptions(options)); + return getTypeLoader().parse(doc.getDocumentElement(), type, getXmlOptions(options)); } catch (SAXException e) { throw new IOException("Unable to parse xml bean", e); } } public static XmlObject parse(XMLStreamReader xsr, SchemaType type, XmlOptions options) throws XmlException { - return XmlBeans.getContextTypeLoader().parse(xsr, type, getXmlOptions(options)); + return getTypeLoader().parse(xsr, type, getXmlOptions(options)); } public static XmlObject parse(Reader jior, SchemaType type, XmlOptions options) throws XmlException, IOException { try { Document doc = DocumentHelper.readDocument(new InputSource(jior)); - return XmlBeans.getContextTypeLoader().parse(doc.getDocumentElement(), type, getXmlOptions(options)); + return getTypeLoader().parse(doc.getDocumentElement(), type, getXmlOptions(options)); } catch (SAXException e) { throw new XmlException("Unable to parse xml bean", e); } } public static XmlObject parse(Node node, SchemaType type, XmlOptions options) throws XmlException { - return XmlBeans.getContextTypeLoader().parse(node, type, getXmlOptions(options)); + return getTypeLoader().parse(node, type, getXmlOptions(options)); } public static XmlObject parse(XMLInputStream xis, SchemaType type, XmlOptions options) throws XmlException, XMLStreamException { - return XmlBeans.getContextTypeLoader().parse(xis, type, getXmlOptions(options)); + return getTypeLoader().parse(xis, type, getXmlOptions(options)); } public static XMLInputStream newValidatingXMLInputStream ( XMLInputStream xis, SchemaType type, XmlOptions options ) throws XmlException, XMLStreamException { - return XmlBeans.getContextTypeLoader().newValidatingXMLInputStream(xis, type, getXmlOptions(options)); + return getTypeLoader().newValidatingXMLInputStream(xis, type, getXmlOptions(options)); } } diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java index 023c8f7b4..61ab6b44d 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFTable.java @@ -19,8 +19,6 @@ package org.apache.poi.xslf.usermodel; -import static org.apache.poi.POIXMLTypeLoader.DEFAULT_XML_OPTIONS; - import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.Collections; @@ -29,7 +27,6 @@ import java.util.List; import javax.xml.namespace.QName; -import org.apache.poi.POIXMLException; import org.apache.poi.sl.draw.DrawFactory; import org.apache.poi.sl.draw.DrawTableShape; import org.apache.poi.sl.draw.DrawTextShape; @@ -37,7 +34,6 @@ import org.apache.poi.sl.usermodel.TableShape; import org.apache.poi.util.Internal; import org.apache.poi.util.Units; import org.apache.xmlbeans.XmlCursor; -import org.apache.xmlbeans.XmlException; import org.apache.xmlbeans.XmlObject; import org.apache.xmlbeans.impl.values.XmlAnyTypeImpl; import org.openxmlformats.schemas.drawingml.x2006.main.CTGraphicalObjectData; @@ -53,6 +49,7 @@ import org.openxmlformats.schemas.presentationml.x2006.main.CTGraphicalObjectFra public class XSLFTable extends XSLFGraphicFrame implements Iterable, TableShape { /* package */ static final String TABLE_URI = "http://schemas.openxmlformats.org/drawingml/2006/table"; + /* package */ static final String DRAWINGML_URI = "http://schemas.openxmlformats.org/drawingml/2006/main"; private CTTable _table; private List _rows; @@ -60,28 +57,30 @@ public class XSLFTable extends XSLFGraphicFrame implements Iterable(trArray.length); - for(CTTableRow row : trArray) { - XSLFTableRow xr = new XSLFTableRow(row, this); - _rows.add(xr); + _rows = new ArrayList(_table.sizeOfTrArray()); + for(CTTableRow row : _table.getTrArray()) { + _rows.add(new XSLFTableRow(row, this)); } updateRowColIndexes(); } @@ -171,13 +170,18 @@ public class XSLFTable extends XSLFGraphicFrame implements Iterable