]> source.dussan.org Git - poi.git/commitdiff
Sonar Fixes + Refactor scattered XML initializations to XMLHelper
authorAndreas Beeker <kiwiwings@apache.org>
Tue, 3 Dec 2019 21:56:47 +0000 (21:56 +0000)
committerAndreas Beeker <kiwiwings@apache.org>
Tue, 3 Dec 2019 21:56:47 +0000 (21:56 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1870769 13f79535-47bb-0310-9956-ffa450edef68

34 files changed:
src/examples/src/org/apache/poi/xssf/eventusermodel/XLSX2CSV.java
src/examples/src/org/apache/poi/xssf/eventusermodel/examples/FromHowTo.java
src/java/org/apache/poi/sl/draw/geom/PresetGeometries.java
src/java/org/apache/poi/util/StaxHelper.java
src/java/org/apache/poi/util/XMLHelper.java
src/ooxml/java/org/apache/poi/ooxml/dev/OOXMLPrettyPrint.java
src/ooxml/java/org/apache/poi/ooxml/util/DocumentHelper.java
src/ooxml/java/org/apache/poi/ooxml/util/POIXMLConstants.java [deleted file]
src/ooxml/java/org/apache/poi/ooxml/util/SAXHelper.java
src/ooxml/java/org/apache/poi/ooxml/util/TransformerHelper.java
src/ooxml/java/org/apache/poi/openxml4j/opc/StreamHelper.java
src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TSPTimeStampService.java
src/ooxml/java/org/apache/poi/xssf/eventusermodel/ReadOnlySharedStringsTable.java
src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFReader.java
src/ooxml/java/org/apache/poi/xssf/extractor/XSSFEventBasedExcelExtractor.java
src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFBuiltinTableStyle.java
src/ooxml/testcases/org/apache/poi/ooxml/util/TestDocumentHelper.java [deleted file]
src/ooxml/testcases/org/apache/poi/ooxml/util/TestSAXHelper.java [deleted file]
src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestContentType.java
src/ooxml/testcases/org/apache/poi/xssf/extractor/TestXSSFExportToXML.java
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java
src/scratchpad/src/org/apache/poi/hssf/converter/ExcelToFoConverter.java
src/scratchpad/src/org/apache/poi/hssf/converter/ExcelToHtmlConverter.java
src/scratchpad/src/org/apache/poi/hwpf/converter/WordToFoConverter.java
src/scratchpad/src/org/apache/poi/hwpf/converter/WordToHtmlConverter.java
src/scratchpad/src/org/apache/poi/hwpf/converter/WordToTextConverter.java
src/scratchpad/testcases/org/apache/poi/hssf/converter/TestExcelConverterSuite.java
src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToConverterSuite.java
src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToFoConverter.java
src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToHtmlConverter.java
src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestBugs.java
src/testcases/org/apache/poi/util/TestStaxHelper.java [deleted file]
src/testcases/org/apache/poi/util/TestXMLHelper.java [new file with mode: 0644]

index 0ed52e9b5f0f1f8736eb4dfd4ce9a97a9fd14952..85300de6f4d982b173e48117cbf992674a1ef2a1 100644 (file)
@@ -30,7 +30,7 @@ import org.apache.poi.openxml4j.opc.PackageAccess;
 import org.apache.poi.ss.usermodel.DataFormatter;
 import org.apache.poi.ss.util.CellAddress;
 import org.apache.poi.ss.util.CellReference;
-import org.apache.poi.ooxml.util.SAXHelper;
+import org.apache.poi.util.XMLHelper;
 import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler.SheetContentsHandler;
 import org.apache.poi.xssf.extractor.XSSFEventBasedExcelExtractor;
 import org.apache.poi.xssf.model.SharedStrings;
@@ -188,7 +188,7 @@ public class XLSX2CSV {
         DataFormatter formatter = new DataFormatter();
         InputSource sheetSource = new InputSource(sheetInputStream);
         try {
-            XMLReader sheetParser = SAXHelper.newXMLReader();
+            XMLReader sheetParser = XMLHelper.newXMLReader();
             ContentHandler handler = new XSSFSheetXMLHandler(
                   styles, null, strings, sheetHandler, formatter, false);
             sheetParser.setContentHandler(handler);
index cbb7990c5dc0f52943b99b157d8f3921a1776841..f45cac0a917c4fb98e97bb5aa956a2696b4246af 100644 (file)
@@ -23,13 +23,13 @@ import java.util.Map;
 
 import javax.xml.parsers.ParserConfigurationException;
 
+import org.apache.poi.openxml4j.opc.OPCPackage;
 import org.apache.poi.openxml4j.opc.PackageAccess;
-import org.apache.poi.ooxml.util.SAXHelper;
+import org.apache.poi.util.XMLHelper;
 import org.apache.poi.xssf.eventusermodel.XLSX2CSV;
 import org.apache.poi.xssf.eventusermodel.XSSFReader;
 import org.apache.poi.xssf.model.SharedStringsTable;
 import org.apache.poi.xssf.usermodel.XSSFRichTextString;
-import org.apache.poi.openxml4j.opc.OPCPackage;
 import org.xml.sax.Attributes;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.InputSource;
@@ -78,7 +78,7 @@ public class FromHowTo {
     }
 
     public XMLReader fetchSheetParser(SharedStringsTable sst) throws SAXException, ParserConfigurationException {
-        XMLReader parser = SAXHelper.newXMLReader();
+        XMLReader parser = XMLHelper.newXMLReader();
         ContentHandler handler = new SheetHandler(sst);
         parser.setContentHandler(handler);
         return parser;
index c010defc0b3d707b2421c7f71860964cfb9ae363..98b2d58fa323121c66e76033e3ce6f7890d3f18f 100644 (file)
@@ -35,7 +35,7 @@ import javax.xml.transform.stream.StreamSource;
 import org.apache.poi.sl.draw.binding.CTCustomGeometry2D;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
-import org.apache.poi.util.StaxHelper;
+import org.apache.poi.util.XMLHelper;
 
 /**
  * 
@@ -50,7 +50,7 @@ public class PresetGeometries extends LinkedHashMap<String, CustomGeometry> {
 
     @SuppressWarnings("unused")
     public void init(InputStream is) throws XMLStreamException, JAXBException {
-        XMLInputFactory staxFactory = StaxHelper.newXMLInputFactory();
+        XMLInputFactory staxFactory = XMLHelper.newXMLInputFactory();
         XMLStreamReader streamReader = staxFactory.createXMLStreamReader(new StreamSource(is));
         try {
             // ignore StartElement:
index 1ce05b9eff097fe17f323737288e6658797d8a7c..e612d92e7f8fbe0885db24a1714afef4dbf780d6 100644 (file)
@@ -17,8 +17,6 @@
 
 package org.apache.poi.util;
 
-import java.util.function.Consumer;
-
 import javax.xml.stream.XMLEventFactory;
 import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLOutputFactory;
@@ -26,50 +24,33 @@ import javax.xml.stream.XMLOutputFactory;
 
 /**
  * Provides handy methods for working with StAX parsers and readers
+ *
+ * @deprecated use {@link XMLHelper}
  */
+@Deprecated
+@Removal(version = "5.0.0")
 public final class StaxHelper {
-    private static final POILogger logger = POILogFactory.getLogger(StaxHelper.class);
-
     private StaxHelper() {
     }
 
     /**
      * Creates a new StAX XMLInputFactory, with sensible defaults
      */
-    @SuppressWarnings({"squid:S2755"})
     public static XMLInputFactory newXMLInputFactory() {
-        XMLInputFactory factory = XMLInputFactory.newInstance();
-        trySet(XMLInputFactory.IS_NAMESPACE_AWARE, (n) -> factory.setProperty(n, true));
-        trySet(XMLInputFactory.IS_VALIDATING, (n) -> factory.setProperty(n, false));
-        trySet(XMLInputFactory.SUPPORT_DTD, (n) -> factory.setProperty(n, false));
-        trySet(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, (n) -> factory.setProperty(n, false));
-        return factory;
+        return XMLHelper.newXMLInputFactory();
     }
 
     /**
      * Creates a new StAX XMLOutputFactory, with sensible defaults
      */
     public static XMLOutputFactory newXMLOutputFactory() {
-        XMLOutputFactory factory = XMLOutputFactory.newInstance();
-        trySet(XMLOutputFactory.IS_REPAIRING_NAMESPACES, (n) -> factory.setProperty(n, true));
-        return factory;
+        return XMLHelper.newXMLOutputFactory();
     }
 
     /**
      * Creates a new StAX XMLEventFactory, with sensible defaults
      */
     public static XMLEventFactory newXMLEventFactory() {
-        // this method seems safer on Android than getFactory()
-        return XMLEventFactory.newInstance();
-    }
-
-    private static void trySet(String name, Consumer<String> securityFeature) {
-        try {
-            securityFeature.accept(name);
-        } catch (Exception e) {
-            logger.log(POILogger.WARN, "StAX Property unsupported", name, e);
-        } catch (AbstractMethodError ame) {
-            logger.log(POILogger.WARN, "Cannot set StAX property because outdated StAX parser in classpath", name, ame);
-        }
+        return XMLHelper.newXMLEventFactory();
     }
 }
index 9c29546eba8e0e37c3bf0f3ea3f2038a516dd79f..fd02caca2f1015e5705e4c1916fe61adc8ccaa6d 100644 (file)
 
 package org.apache.poi.util;
 
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.util.concurrent.TimeUnit;
+
 import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.stream.XMLEventFactory;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.validation.SchemaFactory;
+
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
 
 /**
  * Helper methods for working with javax.xml classes.
  */
+@Internal
 public final class XMLHelper {
+    static final String FEATURE_LOAD_DTD_GRAMMAR = "http://apache.org/xml/features/nonvalidating/load-dtd-grammar";
+    static final String FEATURE_LOAD_EXTERNAL_DTD = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
+    static final String FEATURE_DISALLOW_DOCTYPE_DECL = "http://apache.org/xml/features/disallow-doctype-decl";
+    static final String FEATURE_PARAMETER_ENTITIES = "http://xml.org/sax/features/external-parameter-entities";
+    static final String FEATURE_EXTERNAL_ENTITIES = "http://xml.org/sax/features/external-general-entities";
+    static final String PROPERTY_ENTITY_EXPANSION_LIMIT = "http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit";
+    static final String PROPERTY_SECURITY_MANAGER = "http://apache.org/xml/properties/security-manager";
+    static final String METHOD_ENTITY_EXPANSION_XERCES = "setEntityExpansionLimit";
+
+    static final String[] SECURITY_MANAGERS = {
+            //"com.sun.org.apache.xerces.internal.util.SecurityManager",
+            "org.apache.xerces.util.SecurityManager"
+    };
+
+
     private static POILogger logger = POILogFactory.getLogger(XMLHelper.class);
+    private static long lastLog;
+
+    // DocumentBuilderFactory.newDocumentBuilder is thread-safe
+    // see https://stackoverflow.com/questions/12455602/is-documentbuilder-thread-safe
+    private static final DocumentBuilderFactory documentBuilderFactory = getDocumentBuilderFactory();
+
+    private static final SAXParserFactory saxFactory = getSaxParserFactory();
 
     @FunctionalInterface
     private interface SecurityFeature {
-        void accept(String name) throws ParserConfigurationException;
+        void accept(String name, boolean value) throws ParserConfigurationException, SAXException, TransformerException;
+    }
+
+    @FunctionalInterface
+    private interface SecurityProperty {
+        void accept(String name, Object value) throws SAXException;
+    }
+
+    private XMLHelper() {
     }
 
     /**
@@ -40,26 +92,225 @@ public final class XMLHelper {
     @SuppressWarnings({"squid:S2755"})
     public static DocumentBuilderFactory getDocumentBuilderFactory() {
         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware(true);
+        // this doesn't appear to work, and we still need to limit
+        // entity expansions to 1 in trySetXercesSecurityManager
         factory.setExpandEntityReferences(false);
-        trySet(XMLConstants.FEATURE_SECURE_PROCESSING, (n) -> factory.setFeature(n, true));
-        trySet(XMLConstants.ACCESS_EXTERNAL_SCHEMA, (n) -> factory.setAttribute(n, ""));
-        trySet(XMLConstants.ACCESS_EXTERNAL_DTD, (n) -> factory.setAttribute(n, ""));
-        trySet("http://xml.org/sax/features/external-general-entities", (n) -> factory.setFeature(n, false));
-        trySet("http://xml.org/sax/features/external-parameter-entities", (n) -> factory.setFeature(n, false));
-        trySet("http://apache.org/xml/features/nonvalidating/load-external-dtd", (n) -> factory.setFeature(n, false));
-        trySet("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", (n) -> factory.setFeature(n, false));
-        trySet("http://apache.org/xml/features/disallow-doctype-decl", (n) -> factory.setFeature(n, true));
-        trySet("XIncludeAware", (n) -> factory.setXIncludeAware(false));
+        factory.setValidating(false);
+        trySet(factory::setFeature, XMLConstants.FEATURE_SECURE_PROCESSING, true);
+        trySet(factory::setAttribute, XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
+        trySet(factory::setAttribute, XMLConstants.ACCESS_EXTERNAL_DTD, "");
+        trySet(factory::setFeature, FEATURE_EXTERNAL_ENTITIES, false);
+        trySet(factory::setFeature, FEATURE_PARAMETER_ENTITIES, false);
+        trySet(factory::setFeature, FEATURE_LOAD_EXTERNAL_DTD, false);
+        trySet(factory::setFeature, FEATURE_LOAD_DTD_GRAMMAR, false);
+        trySet(factory::setFeature, FEATURE_DISALLOW_DOCTYPE_DECL, true);
+        trySet((n, b) -> factory.setXIncludeAware(b), "XIncludeAware", false);
+
+        Object manager = getXercesSecurityManager();
+        if (manager == null || !trySet(factory::setAttribute, PROPERTY_SECURITY_MANAGER, manager)) {
+            // separate old version of Xerces not found => use the builtin way of setting the property
+            // Note: when entity_expansion_limit==0, there is no limit!
+            trySet(factory::setAttribute, PROPERTY_ENTITY_EXPANSION_LIMIT, 1);
+        }
+
+        return factory;
+    }
+
+    /**
+     * Creates a new document builder, with sensible defaults
+     *
+     * @throws IllegalStateException If creating the DocumentBuilder fails, e.g.
+     *                               due to {@link ParserConfigurationException}.
+     */
+    public static DocumentBuilder newDocumentBuilder() {
+        try {
+            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+            documentBuilder.setEntityResolver(XMLHelper::ignoreEntity);
+            documentBuilder.setErrorHandler(new DocHelperErrorHandler());
+            return documentBuilder;
+        } catch (ParserConfigurationException e) {
+            throw new IllegalStateException("cannot create a DocumentBuilder", e);
+        }
+    }
+
+    public static SAXParserFactory getSaxParserFactory() {
+        try {
+            SAXParserFactory factory = SAXParserFactory.newInstance();
+            factory.setValidating(false);
+            factory.setNamespaceAware(true);
+            trySet(factory::setFeature, XMLConstants.FEATURE_SECURE_PROCESSING, true);
+            trySet(factory::setFeature, FEATURE_LOAD_DTD_GRAMMAR, false);
+            trySet(factory::setFeature, FEATURE_LOAD_EXTERNAL_DTD, false);
+            return factory;
+        } catch (RuntimeException | Error re) { // NOSONAR
+            // this also catches NoClassDefFoundError, which may be due to a local class path issue
+            // This may occur if the code is run inside a web container or a restricted JVM
+            // See bug 61170: https://bz.apache.org/bugzilla/show_bug.cgi?id=61170
+            logThrowable(re, "Failed to create SAXParserFactory", "-");
+            throw re;
+        } catch (Exception e) {
+            logThrowable(e, "Failed to create SAXParserFactory", "-");
+            throw new RuntimeException("Failed to create SAXParserFactory", e);
+        }
+    }
+
+    /**
+     * Creates a new SAX XMLReader, with sensible defaults
+     */
+    public static XMLReader newXMLReader() throws SAXException, ParserConfigurationException {
+        XMLReader xmlReader = saxFactory.newSAXParser().getXMLReader();
+        xmlReader.setEntityResolver(XMLHelper::ignoreEntity);
+        trySet(xmlReader::setFeature, XMLConstants.FEATURE_SECURE_PROCESSING, true);
+        Object manager = getXercesSecurityManager();
+        if (manager == null || !trySet(xmlReader::setProperty, PROPERTY_SECURITY_MANAGER, manager)) {
+            // separate old version of Xerces not found => use the builtin way of setting the property
+            trySet(xmlReader::setProperty, PROPERTY_ENTITY_EXPANSION_LIMIT, 1);
+        }
+        return xmlReader;
+    }
+
+    /**
+     * Creates a new StAX XMLInputFactory, with sensible defaults
+     */
+    @SuppressWarnings({"squid:S2755"})
+    public static XMLInputFactory newXMLInputFactory() {
+        XMLInputFactory factory = XMLInputFactory.newInstance();
+        trySet(factory::setProperty, XMLInputFactory.IS_NAMESPACE_AWARE, true);
+        trySet(factory::setProperty, XMLInputFactory.IS_VALIDATING, false);
+        trySet(factory::setProperty, XMLInputFactory.SUPPORT_DTD, false);
+        trySet(factory::setProperty, XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
+        return factory;
+    }
+
+    /**
+     * Creates a new StAX XMLOutputFactory, with sensible defaults
+     */
+    public static XMLOutputFactory newXMLOutputFactory() {
+        XMLOutputFactory factory = XMLOutputFactory.newInstance();
+        trySet(factory::setProperty, XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
         return factory;
     }
 
-    private static void trySet(String name, SecurityFeature feature) {
+    /**
+     * Creates a new StAX XMLEventFactory, with sensible defaults
+     */
+    public static XMLEventFactory newXMLEventFactory() {
+        // this method seems safer on Android than getFactory()
+        return XMLEventFactory.newInstance();
+    }
+
+    public static TransformerFactory getTransformerFactory() {
+        TransformerFactory factory = TransformerFactory.newInstance();
+        trySet(factory::setFeature, XMLConstants.FEATURE_SECURE_PROCESSING, true);
+        return factory;
+    }
+
+    public static Transformer newTransformer() throws TransformerConfigurationException {
+        Transformer serializer = getTransformerFactory().newTransformer();
+        // TODO set encoding from a command argument
+        serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+        serializer.setOutputProperty(OutputKeys.INDENT, "no");
+        serializer.setOutputProperty(OutputKeys.METHOD, "xml");
+        return serializer;
+    }
+
+    public static SchemaFactory getSchemaFactory() {
+        SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+        trySet(factory::setFeature, XMLConstants.FEATURE_SECURE_PROCESSING, true);
+        trySet(factory::setProperty, XMLConstants.ACCESS_EXTERNAL_DTD, "");
+        trySet(factory::setProperty, XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
+        return factory;
+    }
+
+
+    private static Object getXercesSecurityManager() {
+        // Try built-in JVM one first, standalone if not
+        for (String securityManagerClassName : SECURITY_MANAGERS) {
+            try {
+                Object mgr = Class.forName(securityManagerClassName).newInstance();
+                Method setLimit = mgr.getClass().getMethod(METHOD_ENTITY_EXPANSION_XERCES, Integer.TYPE);
+                setLimit.invoke(mgr, 1);
+                // Stop once one can be setup without error
+                return mgr;
+            } catch (ClassNotFoundException ignored) {
+                // continue without log, this is expected in some setups
+            } catch (Throwable e) {     // NOSONAR - also catch things like NoClassDefError here
+                logThrowable(e, "SAX Feature unsupported", securityManagerClassName);
+            }
+        }
+
+        return null;
+    }
+
+    @SuppressWarnings("UnusedReturnValue")
+    private static boolean trySet(SecurityFeature feature, String name, boolean value) {
         try {
-            feature.accept(name);
+            feature.accept(name, value);
+            return true;
         } catch (Exception e) {
-            logger.log(POILogger.WARN, "SAX Feature unsupported", name, e);
+            logThrowable(e, "SAX Feature unsupported", name);
         } catch (AbstractMethodError ame) {
-            logger.log(POILogger.WARN, "Cannot set SAX feature because outdated XML parser in classpath", name, ame);
+            logThrowable(ame, "Cannot set SAX feature because outdated XML parser in classpath", name);
         }
+        return false;
+    }
+
+    private static boolean trySet(SecurityProperty property, String name, Object value) {
+        try {
+            property.accept(name, value);
+            return true;
+        } catch (Exception e) {
+            logThrowable(e, "SAX Feature unsupported", name);
+        } catch (AbstractMethodError ame) {
+            logThrowable(ame, "Cannot set SAX feature because outdated XML parser in classpath", name);
+        }
+        return false;
+    }
+
+    private static void logThrowable(Throwable t, String message, String name) {
+        if (System.currentTimeMillis() > lastLog + TimeUnit.MINUTES.toMillis(5)) {
+            logger.log(POILogger.WARN, message + " [log suppressed for 5 minutes]", name, t);
+            lastLog = System.currentTimeMillis();
+        }
+    }
+
+    private static class DocHelperErrorHandler implements ErrorHandler {
+
+        public void warning(SAXParseException exception) {
+            printError(POILogger.WARN, exception);
+        }
+
+        public void error(SAXParseException exception) {
+            printError(POILogger.ERROR, exception);
+        }
+
+        public void fatalError(SAXParseException exception) throws SAXException {
+            printError(POILogger.FATAL, exception);
+            throw exception;
+        }
+
+        /**
+         * Prints the error message.
+         */
+        private void printError(int type, SAXParseException ex) {
+            String systemId = ex.getSystemId();
+            if (systemId != null) {
+                int index = systemId.lastIndexOf('/');
+                if (index != -1) {
+                    systemId = systemId.substring(index + 1);
+                }
+            }
+            String message = (systemId == null ? "" : systemId) +
+                    ':' + ex.getLineNumber() +
+                    ':' + ex.getColumnNumber() +
+                    ':' + ex.getMessage();
+
+            logger.log(type, message, ex);
+        }
+    }
+
+    private static InputSource ignoreEntity(String publicId, String systemId) {
+        return new InputSource(new StringReader(""));
     }
 }
index 8e8b9571d1ab96a3b8e2f21e3113585b5e48cd32..fd48c05462ecc658991de27c738b4eee3596de56 100644 (file)
 ==================================================================== */
 package org.apache.poi.ooxml.dev;
 
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
 import org.apache.poi.ooxml.util.DocumentHelper;
-import org.apache.poi.ooxml.util.TransformerHelper;
 import org.apache.poi.openxml4j.opc.internal.ZipHelper;
 import org.apache.poi.openxml4j.util.ZipSecureFile;
 import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.XMLHelper;
 import org.w3c.dom.Document;
 import org.xml.sax.InputSource;
 
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.transform.*;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-import java.io.*;
-import java.util.Enumeration;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipOutputStream;
-
 /**
  * Reads a zipped OOXML file and produces a copy with the included
  * pretty-printed XML files.
@@ -42,6 +51,8 @@ import java.util.zip.ZipOutputStream;
  *  use different formatting of the XML.
  */
 public class OOXMLPrettyPrint {
+    private static final String XML_INDENT_AMOUNT = "{http://xml.apache.org/xslt}indent-amount";
+
     private final DocumentBuilder documentBuilder;
 
     public OOXMLPrettyPrint() {
@@ -109,13 +120,11 @@ public class OOXMLPrettyPrint {
     }
 
     private static void pretty(Document document, OutputStream outputStream, int indent) throws TransformerException {
-        TransformerFactory transformerFactory = TransformerHelper.getFactory();
-        Transformer transformer = transformerFactory.newTransformer();
-        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
+        Transformer transformer = XMLHelper.newTransformer();
         if (indent > 0) {
             // set properties to indent the resulting XML nicely
             transformer.setOutputProperty(OutputKeys.INDENT, "yes");
-            transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", Integer.toString(indent));
+            transformer.setOutputProperty(XML_INDENT_AMOUNT, Integer.toString(indent));
         }
         Result result = new StreamResult(outputStream);
         Source source = new DOMSource(document);
index 4e66f46b9caac8a8c5641a426139f8cda1a925f2..f5a2b1399686d08deeb3adc4839944d201e0d2bc 100644 (file)
@@ -19,66 +19,24 @@ package org.apache.poi.ooxml.util;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.lang.reflect.Method;
-import java.util.concurrent.TimeUnit;
 
 import javax.xml.XMLConstants;
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.stream.events.Namespace;
 
-import org.apache.poi.util.POILogFactory;
-import org.apache.poi.util.POILogger;
-import org.w3c.dom.*;
-import org.xml.sax.ErrorHandler;
+import org.apache.poi.util.XMLHelper;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
 import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
 
 public final class DocumentHelper {
-    private static POILogger logger = POILogFactory.getLogger(DocumentHelper.class);
-    private static long lastLog;
+    // must only be used to create empty documents, do not use it for parsing!
+    private static final DocumentBuilder documentBuilderSingleton = newDocumentBuilder();
 
     private DocumentHelper() {}
 
-    private static class DocHelperErrorHandler implements ErrorHandler {
-
-        public void warning(SAXParseException exception) {
-            printError(POILogger.WARN, exception);
-        }
-
-        public void error(SAXParseException exception) {
-            printError(POILogger.ERROR, exception);
-        }
-
-        public void fatalError(SAXParseException exception) throws SAXException {
-            printError(POILogger.FATAL, exception);
-            throw exception;
-        }
-
-        /** Prints the error message. */
-        private void printError(int type, SAXParseException ex) {
-            StringBuilder sb = new StringBuilder();
-            
-            String systemId = ex.getSystemId();
-            if (systemId != null) {
-                int index = systemId.lastIndexOf('/');
-                if (index != -1)
-                    systemId = systemId.substring(index + 1);
-                sb.append(systemId);
-            }
-            sb.append(':');
-            sb.append(ex.getLineNumber());
-            sb.append(':');
-            sb.append(ex.getColumnNumber());
-            sb.append(": ");
-            sb.append(ex.getMessage());
-
-            logger.log(type, sb.toString(), ex);
-        }
-    }
-    
     /**
      * Creates a new document builder, with sensible defaults
      *
@@ -86,80 +44,14 @@ public final class DocumentHelper {
      *  due to {@link ParserConfigurationException}.
      */
     public static DocumentBuilder newDocumentBuilder() {
-        try {
-            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
-            documentBuilder.setEntityResolver(SAXHelper.IGNORING_ENTITY_RESOLVER);
-            documentBuilder.setErrorHandler(new DocHelperErrorHandler());
-            return documentBuilder;
-        } catch (ParserConfigurationException e) {
-            throw new IllegalStateException("cannot create a DocumentBuilder", e);
-        }
-    }
-
-    static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
-    static {
-        documentBuilderFactory.setNamespaceAware(true);
-        documentBuilderFactory.setValidating(false);
-        //this doesn't appear to work, and we still need to limit
-        //entity expansions to 1 in trySetXercesSecurityManager
-        documentBuilderFactory.setExpandEntityReferences(false);
-        trySetFeature(documentBuilderFactory, XMLConstants.FEATURE_SECURE_PROCESSING, true);
-        trySetFeature(documentBuilderFactory, POIXMLConstants.FEATURE_DISALLOW_DOCTYPE_DECL, true);
-        trySetFeature(documentBuilderFactory, POIXMLConstants.FEATURE_LOAD_DTD_GRAMMAR, false);
-        trySetFeature(documentBuilderFactory, POIXMLConstants.FEATURE_LOAD_EXTERNAL_DTD, false);
-        trySetXercesSecurityManager(documentBuilderFactory);
-    }
-
-    private static void trySetFeature(@SuppressWarnings("SameParameterValue") DocumentBuilderFactory dbf, String feature, boolean enabled) {
-        try {
-            dbf.setFeature(feature, enabled);
-        } catch (Exception e) {
-            logger.log(POILogger.WARN, "DocumentBuilderFactory Feature unsupported", feature, e);
-        } catch (AbstractMethodError ame) {
-            logger.log(POILogger.WARN, "Cannot set DocumentBuilderFactory feature because outdated XML parser in classpath", feature, ame);
-        }
-    }
-    
-    private static void trySetXercesSecurityManager(@SuppressWarnings("SameParameterValue") DocumentBuilderFactory dbf) {
-        // Try built-in JVM one first, standalone if not
-        for (String securityManagerClassName : new String[]{
-                //"com.sun.org.apache.xerces.internal.util.SecurityManager",
-                "org.apache.xerces.util.SecurityManager"
-        }) {
-            try {
-                Object mgr = Class.forName(securityManagerClassName).newInstance();
-                Method setLimit = mgr.getClass().getMethod("setEntityExpansionLimit", Integer.TYPE);
-                setLimit.invoke(mgr, 1);
-                dbf.setAttribute(POIXMLConstants.PROPERTY_SECURITY_MANAGER, mgr);
-                // Stop once one can be setup without error
-                return;
-            } catch (ClassNotFoundException e) {
-                // continue without log, this is expected in some setups
-            } catch (Throwable e) {     // NOSONAR - also catch things like NoClassDefError here
-                if(System.currentTimeMillis() > lastLog + TimeUnit.MINUTES.toMillis(5)) {
-                    logger.log(POILogger.WARN, "DocumentBuilderFactory Security Manager could not be setup [log suppressed for 5 minutes]", e);
-                    lastLog = System.currentTimeMillis();
-                }
-            }
-        }
-
-        // separate old version of Xerces not found => use the builtin way of setting the property
-        // Note: when entity_expansion_limit==0, there is no limit!
-        try {
-            dbf.setAttribute(POIXMLConstants.PROPERTY_ENTITY_EXPANSION_LIMIT, 1);
-        } catch (Throwable e) {
-            if(System.currentTimeMillis() > lastLog + TimeUnit.MINUTES.toMillis(5)) {
-                logger.log(POILogger.WARN, "DocumentBuilderFactory Entity Expansion Limit could not be setup [log suppressed for 5 minutes]", e);
-                lastLog = System.currentTimeMillis();
-            }
-        }
+        return XMLHelper.newDocumentBuilder();
     }
 
     /**
      * Parses the given stream via the default (sensible)
      * DocumentBuilder
      * @param inp Stream to read the XML data from
-     * @return the parsed Document 
+     * @return the parsed Document
      */
     public static Document readDocument(InputStream inp) throws IOException, SAXException {
         return newDocumentBuilder().parse(inp);
@@ -175,9 +67,6 @@ public final class DocumentHelper {
         return newDocumentBuilder().parse(inp);
     }
 
-    // must only be used to create empty documents, do not use it for parsing!
-    private static final DocumentBuilder documentBuilderSingleton = newDocumentBuilder();
-
     /**
      * Creates a new DOM Document
      */
diff --git a/src/ooxml/java/org/apache/poi/ooxml/util/POIXMLConstants.java b/src/ooxml/java/org/apache/poi/ooxml/util/POIXMLConstants.java
deleted file mode 100644 (file)
index c6d7935..0000000
+++ /dev/null
@@ -1,26 +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;
-
-public class POIXMLConstants {
-    public static final String FEATURE_LOAD_DTD_GRAMMAR = "http://apache.org/xml/features/nonvalidating/load-dtd-grammar";
-    public static final String FEATURE_LOAD_EXTERNAL_DTD = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
-    public static final String FEATURE_DISALLOW_DOCTYPE_DECL = "http://apache.org/xml/features/disallow-doctype-decl";
-    public static final String PROPERTY_ENTITY_EXPANSION_LIMIT = "http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit";
-    public static final String PROPERTY_SECURITY_MANAGER = "http://apache.org/xml/properties/security-manager";
-}
index ede0ac4582e7075a16d0f8ee79c6c72f5c154640..a6c2b58485797c29db3528f7cc2ff11c96a71f87 100644 (file)
 
 package org.apache.poi.ooxml.util;
 
-import java.io.StringReader;
-import java.lang.reflect.Method;
-import java.util.concurrent.TimeUnit;
-
-import javax.xml.XMLConstants;
 import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParserFactory;
 
-import org.apache.poi.util.POILogFactory;
-import org.apache.poi.util.POILogger;
-import org.xml.sax.EntityResolver;
-import org.xml.sax.InputSource;
+import org.apache.poi.util.Removal;
+import org.apache.poi.util.XMLHelper;
 import org.xml.sax.SAXException;
 import org.xml.sax.XMLReader;
 
 
 /**
  * Provides handy methods for working with SAX parsers and readers
+ * @deprecated use {@link XMLHelper}
  */
+@Deprecated
+@Removal(version = "5.0.0")
 public final class SAXHelper {
-    private static final POILogger logger = POILogFactory.getLogger(SAXHelper.class);
-    private static long lastLog;
-
-    private SAXHelper() {}
-
     /**
      * Creates a new SAX XMLReader, with sensible defaults
      */
     public static XMLReader newXMLReader() throws SAXException, ParserConfigurationException {
-        XMLReader xmlReader = saxFactory.newSAXParser().getXMLReader();
-        xmlReader.setEntityResolver(IGNORING_ENTITY_RESOLVER);
-        trySetSAXFeature(xmlReader, XMLConstants.FEATURE_SECURE_PROCESSING);
-        trySetXercesSecurityManager(xmlReader);
-        return xmlReader;
-    }
-    
-    static final EntityResolver IGNORING_ENTITY_RESOLVER = (publicId, systemId) -> new InputSource(new StringReader(""));
-    
-    private static final SAXParserFactory saxFactory;
-    static {
-        try {
-            saxFactory = SAXParserFactory.newInstance();
-            saxFactory.setValidating(false);
-            saxFactory.setNamespaceAware(true);
-            trySetSAXFeature(saxFactory, XMLConstants.FEATURE_SECURE_PROCESSING, true);
-            trySetSAXFeature(saxFactory, POIXMLConstants.FEATURE_LOAD_DTD_GRAMMAR, false);
-            trySetSAXFeature(saxFactory, POIXMLConstants.FEATURE_LOAD_EXTERNAL_DTD, false);
-        } catch (RuntimeException | Error re) { // NOSONAR
-            // this also catches NoClassDefFoundError, which may be due to a local class path issue
-            // This may occur if the code is run inside a web container
-            // or a restricted JVM
-            // See bug 61170: https://bz.apache.org/bugzilla/show_bug.cgi?id=61170
-            logger.log(POILogger.WARN, "Failed to create SAXParserFactory", re);
-            throw re;
-        } catch (Exception e) {
-            logger.log(POILogger.WARN, "Failed to create SAXParserFactory", e);
-            throw new RuntimeException("Failed to create SAXParserFactory", e);
-        }
-    }
-            
-    private static void trySetSAXFeature(@SuppressWarnings("SameParameterValue") SAXParserFactory spf,
-                                         String feature, boolean flag) {
-        try {
-            spf.setFeature(feature, flag);
-        } catch (Exception e) {
-            logger.log(POILogger.WARN, "SAX Feature unsupported", feature, e);
-        } catch (AbstractMethodError ame) {
-            logger.log(POILogger.WARN, "Cannot set SAX feature because outdated XML parser in classpath", feature, ame);
-        }
-    }
-
-    private static void trySetSAXFeature(XMLReader xmlReader, @SuppressWarnings("SameParameterValue") String feature) {
-        try {
-            xmlReader.setFeature(feature, true);
-        } catch (Exception e) {
-            logger.log(POILogger.WARN, "SAX Feature unsupported", feature, e);
-        } catch (AbstractMethodError ame) {
-            logger.log(POILogger.WARN, "Cannot set SAX feature because outdated XML parser in classpath", feature, ame);
-        }
-    }
-    
-    private static void trySetXercesSecurityManager(XMLReader xmlReader) {
-        // Try built-in JVM one first, standalone if not
-        for (String securityManagerClassName : new String[] {
-                //"com.sun.org.apache.xerces.internal.util.SecurityManager",
-                "org.apache.xerces.util.SecurityManager"
-        }) {
-            try {
-                Object mgr = Class.forName(securityManagerClassName).newInstance();
-                Method setLimit = mgr.getClass().getMethod("setEntityExpansionLimit", Integer.TYPE);
-                setLimit.invoke(mgr, 1);
-                xmlReader.setProperty(POIXMLConstants.PROPERTY_SECURITY_MANAGER, mgr);
-                // Stop once one can be setup without error
-                return;
-            } catch (ClassNotFoundException e) {
-                // continue without log, this is expected in some setups
-            } catch (Throwable e) {     // NOSONAR - also catch things like NoClassDefError here
-                // throttle the log somewhat as it can spam the log otherwise
-                if(System.currentTimeMillis() > lastLog + TimeUnit.MINUTES.toMillis(5)) {
-                    logger.log(POILogger.WARN, "SAX Security Manager could not be setup [log suppressed for 5 minutes]", e);
-                    lastLog = System.currentTimeMillis();
-                }
-            }
-        }
-
-        // separate old version of Xerces not found => use the builtin way of setting the property
-        try {
-            xmlReader.setProperty(POIXMLConstants.PROPERTY_ENTITY_EXPANSION_LIMIT, 1);
-        } catch (SAXException e) {     // NOSONAR - also catch things like NoClassDefError here
-            // throttle the log somewhat as it can spam the log otherwise
-            if(System.currentTimeMillis() > lastLog + TimeUnit.MINUTES.toMillis(5)) {
-                logger.log(POILogger.WARN, "SAX Security Manager could not be setup [log suppressed for 5 minutes]", e);
-                lastLog = System.currentTimeMillis();
-            }
-        }
+        return XMLHelper.newXMLReader();
     }
 }
index 37422c6c9151d625b0b546ddac56ef1cf71f095d..e6a3f0c8f30f98ed482c2137fa47caa7f6c56fcc 100644 (file)
 
 package org.apache.poi.ooxml.util;
 
-import org.apache.poi.util.POILogFactory;
-import org.apache.poi.util.POILogger;
-
-import javax.xml.XMLConstants;
 import javax.xml.transform.TransformerFactory;
 
-public final class TransformerHelper {
-    private static POILogger logger = POILogFactory.getLogger(TransformerHelper.class);
+import org.apache.poi.util.Removal;
+import org.apache.poi.util.XMLHelper;
 
+/**
+ * @deprecated use {@link XMLHelper}
+ */
+@Removal(version = "5.0.0")
+@Deprecated
+public final class TransformerHelper {
     private TransformerHelper() {}
 
-    static final TransformerFactory transformerFactory = TransformerFactory.newInstance();
-    static {
-        trySetFeature(transformerFactory, XMLConstants.FEATURE_SECURE_PROCESSING, true);
-    }
-
     public static TransformerFactory getFactory() {
-        return transformerFactory;
-    }
-
-    private static void trySetFeature(TransformerFactory tf, String feature, boolean enabled) {
-        try {
-            tf.setFeature(feature, enabled);
-        } catch (Exception e) {
-            logger.log(POILogger.WARN, "TransformerFactory Feature unsupported", feature, e);
-        } catch (AbstractMethodError ame) {
-            logger.log(POILogger.WARN, "Cannot set TransformerFactory feature because outdated XML parser in classpath", feature, ame);
-        }
+        return XMLHelper.getTransformerFactory();
     }
 }
index 3c4dc6a2385ec88b592a8e6da10180f8e68ce245..af31eb3ab32e248b242f6e132ac24277ef509ded 100644 (file)
@@ -30,7 +30,8 @@ import javax.xml.transform.TransformerException;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
-import org.apache.poi.ooxml.util.TransformerHelper;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.XMLHelper;
 import org.w3c.dom.Document;
 
 public final class StreamHelper {
@@ -39,10 +40,6 @@ public final class StreamHelper {
                // Do nothing
        }
 
-       private static synchronized Transformer getIdentityTransformer() throws TransformerException {
-               return TransformerHelper.getFactory().newTransformer();
-       }
-
        /**
         * Save the document object in the specified output stream.
         *
@@ -56,7 +53,7 @@ public final class StreamHelper {
        public static boolean saveXmlInStream(Document xmlContent,
                                                                                  OutputStream outStream) {
                try {
-                       Transformer trans = getIdentityTransformer();
+                       Transformer trans = XMLHelper.newTransformer();
                        Source xmlSource = new DOMSource(xmlContent);
                        // prevent close of stream by transformer:
                        Result outputTarget = new StreamResult(new FilterOutputStream(
@@ -97,14 +94,10 @@ public final class StreamHelper {
         */
        public static boolean copyStream(InputStream inStream, OutputStream outStream) {
                try {
-                       byte[] buffer = new byte[1024];
-                       int bytesRead;
-                       while ((bytesRead = inStream.read(buffer)) >= 0) {
-                               outStream.write(buffer, 0, bytesRead);
-                       }
+                       IOUtils.copy(inStream, outStream);
+                       return true;
                } catch (Exception e) {
                        return false;
                }
-               return true;
        }
 }
index ec6a3f0e2dc4399a910de71849724caadc1f7fda..c7fd85c46840db172d0be2b385549d954f35dc81 100644 (file)
@@ -96,7 +96,7 @@ public class TSPTimeStampService implements TimeStampService {
         }
     }
 
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings({"unchecked","squid:S2647"})
     public byte[] timeStamp(byte[] data, RevocationData revocationData)
             throws Exception {
         // digest the message
index 09191f9abf9d504fb14b94f8e2b09c26cf649380..17013e733366fb39a6dfcccede65ffe7d30e453a 100644 (file)
@@ -18,18 +18,19 @@ package org.apache.poi.xssf.eventusermodel;
 
 import static org.apache.poi.xssf.usermodel.XSSFRelation.NS_SPREADSHEETML;
 
-import javax.xml.parsers.ParserConfigurationException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PushbackInputStream;
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.xml.parsers.ParserConfigurationException;
+
 import org.apache.poi.openxml4j.opc.OPCPackage;
 import org.apache.poi.openxml4j.opc.PackagePart;
-import org.apache.poi.ooxml.util.SAXHelper;
 import org.apache.poi.ss.usermodel.RichTextString;
 import org.apache.poi.util.Removal;
+import org.apache.poi.util.XMLHelper;
 import org.apache.poi.xssf.model.SharedStrings;
 import org.apache.poi.xssf.usermodel.XSSFRelation;
 import org.apache.poi.xssf.usermodel.XSSFRichTextString;
@@ -173,7 +174,7 @@ public class ReadOnlySharedStringsTable extends DefaultHandler implements Shared
             pis.unread(emptyTest);
             InputSource sheetSource = new InputSource(pis);
             try {
-                XMLReader sheetParser = SAXHelper.newXMLReader();
+                XMLReader sheetParser = XMLHelper.newXMLReader();
                 sheetParser.setContentHandler(this);
                 sheetParser.parse(sheetSource);
             } catch(ParserConfigurationException e) {
index 8d1ce1a949363a62b4edc2b6e73438ef7171077d..b239951c43921e4c73d8598423fa5a2ada65ed97 100644 (file)
@@ -16,7 +16,6 @@
 ==================================================================== */
 package org.apache.poi.xssf.eventusermodel;
 
-import javax.xml.parsers.ParserConfigurationException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
@@ -30,6 +29,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import javax.xml.parsers.ParserConfigurationException;
+
 import org.apache.poi.ooxml.POIXMLException;
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
@@ -42,7 +43,7 @@ import org.apache.poi.openxml4j.opc.PackageRelationshipTypes;
 import org.apache.poi.openxml4j.opc.PackagingURIHelper;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
-import org.apache.poi.ooxml.util.SAXHelper;
+import org.apache.poi.util.XMLHelper;
 import org.apache.poi.xssf.model.CommentsTable;
 import org.apache.poi.xssf.model.SharedStringsTable;
 import org.apache.poi.xssf.model.StylesTable;
@@ -253,7 +254,7 @@ public class XSSFReader {
             XMLSheetRefReader xmlSheetRefReader = new XMLSheetRefReader();
             XMLReader xmlReader;
             try {
-                xmlReader = SAXHelper.newXMLReader();
+                xmlReader = XMLHelper.newXMLReader();
             } catch (ParserConfigurationException | SAXException e) {
                 throw new POIXMLException(e);
             }
index 526812183df9e371bcae7ba0ccb3f31695b18476..998037b59bba123a20e912b6417b3be7efebadf7 100644 (file)
@@ -16,7 +16,6 @@
 ==================================================================== */
 package org.apache.poi.xssf.extractor;
 
-import javax.xml.parsers.ParserConfigurationException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.HashMap;
@@ -24,6 +23,8 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 
+import javax.xml.parsers.ParserConfigurationException;
+
 import org.apache.poi.ooxml.POIXMLProperties;
 import org.apache.poi.ooxml.POIXMLProperties.CoreProperties;
 import org.apache.poi.ooxml.POIXMLProperties.CustomProperties;
@@ -34,12 +35,15 @@ import org.apache.poi.openxml4j.opc.OPCPackage;
 import org.apache.poi.ss.usermodel.DataFormatter;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
-import org.apache.poi.ooxml.util.SAXHelper;
+import org.apache.poi.util.XMLHelper;
 import org.apache.poi.xssf.eventusermodel.ReadOnlySharedStringsTable;
 import org.apache.poi.xssf.eventusermodel.XSSFReader;
 import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler;
 import org.apache.poi.xssf.eventusermodel.XSSFSheetXMLHandler.SheetContentsHandler;
-import org.apache.poi.xssf.model.*;
+import org.apache.poi.xssf.model.Comments;
+import org.apache.poi.xssf.model.SharedStrings;
+import org.apache.poi.xssf.model.Styles;
+import org.apache.poi.xssf.model.StylesTable;
 import org.apache.poi.xssf.usermodel.XSSFComment;
 import org.apache.poi.xssf.usermodel.XSSFShape;
 import org.apache.poi.xssf.usermodel.XSSFSimpleShape;
@@ -244,7 +248,7 @@ public class XSSFEventBasedExcelExtractor extends POIXMLTextExtractor
 
         InputSource sheetSource = new InputSource(sheetInputStream);
         try {
-            XMLReader sheetParser = SAXHelper.newXMLReader();
+            XMLReader sheetParser = XMLHelper.newXMLReader();
             ContentHandler handler = new XSSFSheetXMLHandler(
                     styles, comments, strings, sheetContentsExtractor, formatter, formulasNotResults);
             sheetParser.setContentHandler(handler);
index e870349b4db3a9c369bbaf573234927d3ef8a2e9..3904b9fd19f48a065bd7aa933af65531efecb76b 100644 (file)
@@ -28,7 +28,6 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Vector;
 
-import javax.xml.XMLConstants;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Source;
 import javax.xml.transform.Transformer;
@@ -40,12 +39,12 @@ import javax.xml.validation.SchemaFactory;
 import javax.xml.validation.Validator;
 
 import org.apache.poi.ooxml.util.DocumentHelper;
-import org.apache.poi.ooxml.util.TransformerHelper;
 import org.apache.poi.ss.usermodel.CellType;
 import org.apache.poi.ss.usermodel.DateUtil;
 import org.apache.poi.util.LocaleUtil;
 import org.apache.poi.util.POILogFactory;
 import org.apache.poi.util.POILogger;
+import org.apache.poi.util.XMLHelper;
 import org.apache.poi.xssf.usermodel.XSSFCell;
 import org.apache.poi.xssf.usermodel.XSSFMap;
 import org.apache.poi.xssf.usermodel.XSSFRow;
@@ -225,7 +224,7 @@ public class XSSFExportToXml implements Comparator<String>{
             //Output the XML
 
             //set up a transformer
-            Transformer trans = TransformerHelper.getFactory().newTransformer();
+            Transformer trans = XMLHelper.newTransformer();
             trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
             trans.setOutputProperty(OutputKeys.INDENT, "yes");
             trans.setOutputProperty(OutputKeys.ENCODING, encoding);
@@ -250,10 +249,7 @@ public class XSSFExportToXml implements Comparator<String>{
     @SuppressWarnings({"squid:S2755"})
     private boolean isValid(Document xml) throws SAXException{
         try {
-            SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
-            trySet(XMLConstants.FEATURE_SECURE_PROCESSING, (n) -> factory.setFeature(n, true));
-            trySet(XMLConstants.ACCESS_EXTERNAL_DTD, (n) -> factory.setProperty(n,""));
-            trySet(XMLConstants.ACCESS_EXTERNAL_SCHEMA, (n) -> factory.setProperty(n,""));
+            SchemaFactory factory = XMLHelper.getSchemaFactory();
 
             Source source = new DOMSource(map.getSchema());
             Schema schema = factory.newSchema(source);
@@ -407,7 +403,7 @@ public class XSSFExportToXml implements Comparator<String>{
         String[] rightTokens = rightXpath.split("/");
         String samePath = "";
 
-        int minLength = leftTokens.length< rightTokens.length? leftTokens.length : rightTokens.length;
+        int minLength = Math.min(leftTokens.length, rightTokens.length);
 
         Node localComplexTypeRootNode = xmlSchema;
 
index 36a3840223c24c3ad2e3033e9a63107ded9ed1da..2ba065b766f93ffc20ffd9dd1ca7e474d88cb442 100644 (file)
@@ -25,22 +25,24 @@ import java.nio.charset.StandardCharsets;
 import java.util.EnumMap;
 import java.util.Map;
 
-import org.apache.poi.ooxml.util.TransformerHelper;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.poi.ooxml.util.DocumentHelper;
 import org.apache.poi.ss.usermodel.DifferentialStyleProvider;
 import org.apache.poi.ss.usermodel.TableStyle;
 import org.apache.poi.ss.usermodel.TableStyleType;
-import org.apache.poi.ooxml.util.DocumentHelper;
 import org.apache.poi.util.IOUtils;
+import org.apache.poi.util.XMLHelper;
 import org.apache.poi.xssf.model.StylesTable;
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
-import javax.xml.transform.*;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-
 /**
  * Table style names defined in the OOXML spec.
  * The actual styling is defined in presetTableStyles.xml
@@ -440,9 +442,8 @@ public enum XSSFBuiltinTableStyle {
     }
 
     private static String writeToString(Node node) throws IOException, TransformerException {
-        TransformerFactory tf = TransformerHelper.getFactory();
         try (StringWriter sw = new StringWriter()){
-            Transformer transformer = tf.newTransformer();
+            Transformer transformer = XMLHelper.newTransformer();
             transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
             transformer.transform(new DOMSource(node), new StreamResult(sw));
             return sw.toString();
diff --git a/src/ooxml/testcases/org/apache/poi/ooxml/util/TestDocumentHelper.java b/src/ooxml/testcases/org/apache/poi/ooxml/util/TestDocumentHelper.java
deleted file mode 100644 (file)
index 3c07f25..0000000
+++ /dev/null
@@ -1,73 +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 org.junit.Test;
-import org.xml.sax.InputSource;
-
-import javax.xml.XMLConstants;
-import javax.xml.parsers.DocumentBuilder;
-import java.io.ByteArrayInputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertTrue;
-
-public class TestDocumentHelper {
-    @Test
-    public void testDocumentBuilder() throws Exception {
-        DocumentBuilder documentBuilder = DocumentHelper.newDocumentBuilder();
-        assertNotSame(documentBuilder, DocumentHelper.newDocumentBuilder());
-        assertTrue(documentBuilder.isNamespaceAware());
-        assertFalse(documentBuilder.isValidating());
-        documentBuilder.parse(new InputSource(new ByteArrayInputStream("<xml></xml>".getBytes(StandardCharsets.UTF_8))));
-    }
-
-    @Test
-    public void testCreatingManyDocumentBuilders() throws Exception {
-        int limit = 1000;
-        ArrayList<CompletableFuture<DocumentBuilder>> futures = new ArrayList<>();
-        for(int i = 0; i < limit; i++) {
-            futures.add(CompletableFuture.supplyAsync(DocumentHelper::newDocumentBuilder));
-        }
-        HashSet<DocumentBuilder> dbs = new HashSet<>();
-        for(CompletableFuture<DocumentBuilder> future : futures) {
-            DocumentBuilder documentBuilder = future.get(10, TimeUnit.SECONDS);
-            assertTrue(documentBuilder.isNamespaceAware());
-            dbs.add(documentBuilder);
-        }
-        assertEquals(limit, dbs.size());
-    }
-
-    @Test
-    public void testDocumentBuilderFactory() throws Exception {
-        try {
-            assertTrue(DocumentHelper.documentBuilderFactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING));
-            assertTrue(DocumentHelper.documentBuilderFactory.getFeature(POIXMLConstants.FEATURE_DISALLOW_DOCTYPE_DECL));
-            assertFalse(DocumentHelper.documentBuilderFactory.getFeature(POIXMLConstants.FEATURE_LOAD_DTD_GRAMMAR));
-            assertFalse(DocumentHelper.documentBuilderFactory.getFeature(POIXMLConstants.FEATURE_LOAD_EXTERNAL_DTD));
-        } catch(AbstractMethodError e) {
-            // ignore exceptions from old parsers that don't support this API (https://bz.apache.org/bugzilla/show_bug.cgi?id=62692)
-        }
-    }
-}
diff --git a/src/ooxml/testcases/org/apache/poi/ooxml/util/TestSAXHelper.java b/src/ooxml/testcases/org/apache/poi/ooxml/util/TestSAXHelper.java
deleted file mode 100644 (file)
index 536194d..0000000
+++ /dev/null
@@ -1,85 +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 static org.junit.Assert.*;
-
-import java.io.ByteArrayInputStream;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.TimeUnit;
-
-import javax.xml.XMLConstants;
-
-import org.junit.Test;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXNotRecognizedException;
-import org.xml.sax.XMLReader;
-
-public class TestSAXHelper {
-    @Test
-    public void testXMLReader() throws Exception {
-        XMLReader reader = SAXHelper.newXMLReader();
-        assertNotSame(reader, SAXHelper.newXMLReader());
-        try {
-            assertTrue(reader.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING));
-            assertFalse(reader.getFeature(POIXMLConstants.FEATURE_LOAD_DTD_GRAMMAR));
-            assertFalse(reader.getFeature(POIXMLConstants.FEATURE_LOAD_EXTERNAL_DTD));
-            assertEquals(SAXHelper.IGNORING_ENTITY_RESOLVER, reader.getEntityResolver());
-            assertNotNull(reader.getProperty(POIXMLConstants.PROPERTY_ENTITY_EXPANSION_LIMIT));
-            assertEquals("1", reader.getProperty(POIXMLConstants.PROPERTY_ENTITY_EXPANSION_LIMIT));
-            assertNotNull(reader.getProperty(POIXMLConstants.PROPERTY_SECURITY_MANAGER));
-        } catch(SAXNotRecognizedException e) {
-            // ignore exceptions from old parsers that don't support these features
-            // (https://bz.apache.org/bugzilla/show_bug.cgi?id=62692)
-        }
-        reader.parse(new InputSource(new ByteArrayInputStream("<xml></xml>".getBytes(StandardCharsets.UTF_8))));
-    }
-
-    @Test
-    public void testCreatingManyXMLReaders() throws Exception {
-        int limit = 1000;
-        ArrayList<CompletableFuture<XMLReader>> futures = new ArrayList<>();
-        for(int i = 0; i < limit; i++) {
-            futures.add(CompletableFuture.supplyAsync(() -> {
-                try {
-                    return SAXHelper.newXMLReader();
-                } catch (RuntimeException e) {
-                    throw e;
-                } catch (Exception e) {
-                    throw new RuntimeException(e);
-                }
-            }));
-        }
-        HashSet<XMLReader> readers = new HashSet<>();
-        for(CompletableFuture<XMLReader> future : futures) {
-            XMLReader reader = future.get(10, TimeUnit.SECONDS);
-            try {
-                assertTrue(reader.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING));
-            } catch (SAXNotRecognizedException e) {
-                // can happen for older XML Parsers, e.g. we have a CI Job which runs with Xerces XML Parser
-                assertTrue("Had Exception about not-recognized SAX feature: " + e + " which is only expected" +
-                                " for Xerces XML Parser, but had parser: " + reader,
-                        reader.getClass().getName().contains("org.apache.xerces"));
-            }
-            readers.add(reader);
-        }
-        assertEquals(limit, readers.size());
-    }
-}
index 9050e01a59d81f56e129abe5dbbc60467721c5cf..3858bc688da94093486a3447082e85b8d490d70f 100644 (file)
 
 package org.apache.poi.openxml4j.opc;
 
-import org.apache.poi.ooxml.util.POIXMLConstants;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.InputStream;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+
 import org.apache.poi.openxml4j.OpenXML4JTestDataSamples;
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.apache.poi.openxml4j.opc.internal.ContentType;
@@ -25,19 +33,13 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 
-import javax.xml.parsers.DocumentBuilderFactory;
-import java.io.InputStream;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
 /**
  * Tests for content type (ContentType class).
  */
 public final class TestContentType {
 
+    private static final String FEATURE_DISALLOW_DOCTYPE_DECL = "http://apache.org/xml/features/disallow-doctype-decl";
+
     @Rule
     public ExpectedException exception = ExpectedException.none();
 
@@ -242,7 +244,7 @@ public final class TestContentType {
     public static boolean isOldXercesActive() {
         DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
         try {
-            dbf.setFeature(POIXMLConstants.FEATURE_DISALLOW_DOCTYPE_DECL, true);
+            dbf.setFeature(FEATURE_DISALLOW_DOCTYPE_DECL, true);
             return false;
         } catch (Exception|AbstractMethodError ignored) {}
         return true;
index 282f02371e7babe3e92c7eff9b9711630f0e7445..e0386b860a0fda5f252d2d8aabe34664a6057393 100644 (file)
@@ -32,15 +32,13 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
 
 import org.apache.poi.ooxml.POIXMLDocumentPart;
+import org.apache.poi.ooxml.util.DocumentHelper;
 import org.apache.poi.ss.usermodel.Cell;
 import org.apache.poi.ss.usermodel.FormulaError;
 import org.apache.poi.ss.usermodel.Row;
 import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ooxml.util.DocumentHelper;
 import org.apache.poi.util.XMLHelper;
 import org.apache.poi.xssf.XSSFTestDataSamples;
 import org.apache.poi.xssf.model.MapInfo;
@@ -48,8 +46,6 @@ import org.apache.poi.xssf.usermodel.XSSFMap;
 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
 import org.junit.Ignore;
 import org.junit.Test;
-import org.xml.sax.EntityResolver;
-import org.xml.sax.InputSource;
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXParseException;
 
@@ -401,7 +397,7 @@ public final class TestXSSFExportToXML {
                 String xmlData = os.toString("UTF-8");
 
                 assertNotNull(xmlData);
-                assertTrue(!xmlData.isEmpty());
+                assertFalse(xmlData.isEmpty());
 
                 String a = xmlData.split("<A>")[1].split("</A>")[0].trim();
                 String a_b = a.split("<B>")[1].split("</B>")[0].trim();
@@ -505,23 +501,11 @@ public final class TestXSSFExportToXML {
         }
     }
 
-    private void parseXML(String xmlData) throws IOException, SAXException, ParserConfigurationException {
-        DocumentBuilderFactory docBuilderFactory = XMLHelper.getDocumentBuilderFactory();
-        docBuilderFactory.setNamespaceAware(true);
-        docBuilderFactory.setValidating(false);
-        DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
-        docBuilder.setEntityResolver(new DummyEntityResolver());
-
+    private void parseXML(String xmlData) throws IOException, SAXException {
+        DocumentBuilder docBuilder = XMLHelper.newDocumentBuilder();
         docBuilder.parse(new ByteArrayInputStream(xmlData.getBytes(StandardCharsets.UTF_8)));
     }
 
-    private static class DummyEntityResolver implements EntityResolver {
-        @Override
-        public InputSource resolveEntity(String publicId, String systemId) {
-            return null;
-        }
-    }
-
     @Test
     public void testExportDataTypes() throws Exception {
         try (XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("55923.xlsx")) {
index da056eb1ead0aa1419165625b47e815a06b76533..9eb2ed9dc7646009df87bbee6828c219a22be56a 100644 (file)
@@ -59,7 +59,6 @@ import org.apache.poi.ooxml.POIXMLDocumentPart.RelationPart;
 import org.apache.poi.ooxml.POIXMLException;
 import org.apache.poi.ooxml.POIXMLProperties;
 import org.apache.poi.ooxml.util.DocumentHelper;
-import org.apache.poi.ooxml.util.SAXHelper;
 import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.apache.poi.openxml4j.exceptions.InvalidOperationException;
 import org.apache.poi.openxml4j.exceptions.OpenXML4JException;
@@ -84,32 +83,7 @@ import org.apache.poi.ss.formula.eval.ErrorEval;
 import org.apache.poi.ss.formula.eval.NumberEval;
 import org.apache.poi.ss.formula.functions.Function;
 import org.apache.poi.ss.formula.ptg.Ptg;
-import org.apache.poi.ss.usermodel.BaseTestBugzillaIssues;
-import org.apache.poi.ss.usermodel.BorderStyle;
-import org.apache.poi.ss.usermodel.Cell;
-import org.apache.poi.ss.usermodel.CellStyle;
-import org.apache.poi.ss.usermodel.CellType;
-import org.apache.poi.ss.usermodel.CellValue;
-import org.apache.poi.ss.usermodel.ClientAnchor;
-import org.apache.poi.ss.usermodel.Comment;
-import org.apache.poi.ss.usermodel.CreationHelper;
-import org.apache.poi.ss.usermodel.DataFormat;
-import org.apache.poi.ss.usermodel.DataFormatter;
-import org.apache.poi.ss.usermodel.DateUtil;
-import org.apache.poi.ss.usermodel.Drawing;
-import org.apache.poi.ss.usermodel.FillPatternType;
-import org.apache.poi.ss.usermodel.Font;
-import org.apache.poi.ss.usermodel.FormulaError;
-import org.apache.poi.ss.usermodel.FormulaEvaluator;
-import org.apache.poi.ss.usermodel.IgnoredErrorType;
-import org.apache.poi.ss.usermodel.IndexedColors;
-import org.apache.poi.ss.usermodel.Name;
-import org.apache.poi.ss.usermodel.PrintSetup;
-import org.apache.poi.ss.usermodel.Row;
-import org.apache.poi.ss.usermodel.Sheet;
-import org.apache.poi.ss.usermodel.SheetConditionalFormatting;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.ss.util.AreaReference;
 import org.apache.poi.ss.util.CellAddress;
 import org.apache.poi.ss.util.CellRangeAddress;
@@ -118,6 +92,7 @@ import org.apache.poi.ss.util.CellUtil;
 import org.apache.poi.util.LocaleUtil;
 import org.apache.poi.util.NullOutputStream;
 import org.apache.poi.util.TempFile;
+import org.apache.poi.util.XMLHelper;
 import org.apache.poi.xssf.SXSSFITestDataProvider;
 import org.apache.poi.xssf.XLSBUnsupportedException;
 import org.apache.poi.xssf.XSSFITestDataProvider;
@@ -1946,7 +1921,7 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues {
         File testFile = XSSFTestDataSamples.getSampleFile("54764.xlsx");
         ZipFile zip = new ZipFile(testFile);
         ZipArchiveEntry ze = zip.getEntry("xl/sharedStrings.xml");
-        XMLReader reader = SAXHelper.newXMLReader();
+        XMLReader reader = XMLHelper.newXMLReader();
         try {
             reader.parse(new InputSource(zip.getInputStream(ze)));
             fail("should have thrown SAXParseException");
index a8d283224032027989879861a80777704c8590cb..0bdaf57c65d2aae7893e4c3ef336f0df276fb911 100644 (file)
@@ -20,9 +20,7 @@ import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
 
-import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
@@ -92,12 +90,8 @@ public class ExcelToFoConverter extends AbstractExcelConverter
         DOMSource domSource = new DOMSource( doc );
         StreamResult streamResult = new StreamResult( new File(args[1]) );
 
-        TransformerFactory tf = TransformerFactory.newInstance();
-        Transformer serializer = tf.newTransformer();
         // TODO set encoding from a command argument
-        serializer.setOutputProperty( OutputKeys.ENCODING, "UTF-8" );
-        serializer.setOutputProperty( OutputKeys.INDENT, "no" );
-        serializer.setOutputProperty( OutputKeys.METHOD, "xml" );
+        Transformer serializer = XMLHelper.newTransformer();
         serializer.transform( domSource, streamResult );
     }
 
@@ -113,8 +107,7 @@ public class ExcelToFoConverter extends AbstractExcelConverter
         final HSSFWorkbook workbook = AbstractExcelUtils.loadXls( xlsFile );
         try {
             ExcelToFoConverter excelToHtmlConverter = new ExcelToFoConverter(
-                    XMLHelper.getDocumentBuilderFactory().newDocumentBuilder()
-                            .newDocument() );
+                    XMLHelper.newDocumentBuilder().newDocument() );
             excelToHtmlConverter.processWorkbook( workbook );
             return excelToHtmlConverter.getDocument();
         } finally {
index 2e173e15d4bbdc38d3998f9aabc110d50fda61e6..e3f5e9aaffbfebab962aac1dbbde3dd12c6d2ffe 100644 (file)
@@ -27,7 +27,6 @@ import java.util.Map;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
@@ -85,11 +84,8 @@ public class ExcelToHtmlConverter extends AbstractExcelConverter {
         DOMSource domSource = new DOMSource( doc );
         StreamResult streamResult = new StreamResult( new File(args[1]) );
 
-        TransformerFactory tf = TransformerFactory.newInstance();
-        Transformer serializer = tf.newTransformer();
+        Transformer serializer = XMLHelper.newTransformer();
         // TODO set encoding from a command argument
-        serializer.setOutputProperty( OutputKeys.ENCODING, "UTF-8" );
-        serializer.setOutputProperty( OutputKeys.INDENT, "no" );
         serializer.setOutputProperty( OutputKeys.METHOD, "html" );
         serializer.transform( domSource, streamResult );
     }
@@ -133,8 +129,7 @@ public class ExcelToHtmlConverter extends AbstractExcelConverter {
      */
     public static Document process( HSSFWorkbook workbook ) throws IOException, ParserConfigurationException {
         ExcelToHtmlConverter excelToHtmlConverter = new ExcelToHtmlConverter(
-                XMLHelper.getDocumentBuilderFactory().newDocumentBuilder()
-                        .newDocument() );
+                XMLHelper.newDocumentBuilder().newDocument() );
         excelToHtmlConverter.processWorkbook( workbook );
         return excelToHtmlConverter.getDocument();
     }
index ad51d4b7cffb09553ad1477e70f7a97dba77810b..9f2bbdba80f4f32fc23df995086f3d99621e7159 100644 (file)
@@ -24,9 +24,7 @@ import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import javax.xml.parsers.DocumentBuilder;
-import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
@@ -86,17 +84,14 @@ public class WordToFoConverter extends AbstractWordConverter
 
         DOMSource domSource = new DOMSource( doc );
         StreamResult streamResult = new StreamResult( new File( args[1] ) );
-        TransformerFactory tf = TransformerFactory.newInstance();
-        Transformer serializer = tf.newTransformer();
         // TODO set encoding from a command argument
-        serializer.setOutputProperty( OutputKeys.ENCODING, "UTF-8" );
-        serializer.setOutputProperty( OutputKeys.INDENT, "yes" );
+        Transformer serializer = XMLHelper.newTransformer();
         serializer.transform( domSource, streamResult );
     }
 
     static Document process( File docFile ) throws Exception
     {
-        final DocumentBuilder docBuild = XMLHelper.getDocumentBuilderFactory().newDocumentBuilder();
+        final DocumentBuilder docBuild = XMLHelper.newDocumentBuilder();
         try (final HWPFDocumentCore hwpfDocument = WordToFoUtils.loadDoc( docFile )) {
             WordToFoConverter wordToFoConverter = new WordToFoConverter(docBuild.newDocument());
             wordToFoConverter.processDocument(hwpfDocument);
index 784fb5028cc843646aa2b10af2e4d2a7006f152c..d3d4f6e57bb85781405caabee70ae35a73b176fb 100644 (file)
@@ -30,7 +30,6 @@ import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
@@ -154,18 +153,15 @@ public class WordToHtmlConverter extends AbstractWordConverter
         DOMSource domSource = new DOMSource( doc );
         StreamResult streamResult = new StreamResult( new File(args[1]) );
 
-        TransformerFactory tf = TransformerFactory.newInstance();
-        Transformer serializer = tf.newTransformer();
+        Transformer serializer = XMLHelper.newTransformer();
         // TODO set encoding from a command argument
-        serializer.setOutputProperty( OutputKeys.ENCODING, "UTF-8" );
-        serializer.setOutputProperty( OutputKeys.INDENT, "yes" );
         serializer.setOutputProperty( OutputKeys.METHOD, "html" );
         serializer.transform( domSource, streamResult );
     }
 
     static Document process( File docFile ) throws IOException, ParserConfigurationException
     {
-        final DocumentBuilder docBuild = XMLHelper.getDocumentBuilderFactory().newDocumentBuilder();
+        final DocumentBuilder docBuild = XMLHelper.newDocumentBuilder();
         try (final HWPFDocumentCore wordDocument = AbstractWordUtils.loadDoc( docFile )) {
             WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(docBuild.newDocument());
             wordToHtmlConverter.processDocument(wordDocument);
index 399029233dc7d8194dd76e8de3c9093c95e97a52..3103c818691d5a831c435e5f7373b47440b5655e 100644 (file)
@@ -76,7 +76,7 @@ public class WordToTextConverter extends AbstractWordConverter
             throws Exception
     {
         WordToTextConverter wordToTextConverter = new WordToTextConverter(
-                XMLHelper.getDocumentBuilderFactory().newDocumentBuilder().newDocument() );
+                XMLHelper.newDocumentBuilder().newDocument() );
         wordToTextConverter.processDocument( wordDocument );
         return wordToTextConverter.getText();
     }
@@ -105,11 +105,8 @@ public class WordToTextConverter extends AbstractWordConverter
         DOMSource domSource = new DOMSource( doc );
         StreamResult streamResult = new StreamResult( new File( args[1] ) );
 
-        TransformerFactory tf = TransformerFactory.newInstance();
-        Transformer serializer = tf.newTransformer();
+        Transformer serializer = XMLHelper.newTransformer();
         // TODO set encoding from a command argument
-        serializer.setOutputProperty( OutputKeys.ENCODING, "UTF-8" );
-        serializer.setOutputProperty( OutputKeys.INDENT, "no" );
         serializer.setOutputProperty( OutputKeys.METHOD, "text" );
         serializer.transform( domSource, streamResult );
     }
@@ -117,7 +114,7 @@ public class WordToTextConverter extends AbstractWordConverter
     private static Document process( File docFile ) throws IOException, ParserConfigurationException {
         try (final HWPFDocumentCore wordDocument = AbstractWordUtils.loadDoc( docFile )) {
             WordToTextConverter wordToTextConverter = new WordToTextConverter(
-                    XMLHelper.getDocumentBuilderFactory().newDocumentBuilder().newDocument());
+                    XMLHelper.newDocumentBuilder().newDocument());
             wordToTextConverter.processDocument(wordDocument);
             return wordToTextConverter.getDocument();
         }
@@ -141,8 +138,7 @@ public class WordToTextConverter extends AbstractWordConverter
     public WordToTextConverter() throws ParserConfigurationException
     {
         this.textDocumentFacade = new TextDocumentFacade(
-                XMLHelper.getDocumentBuilderFactory().newDocumentBuilder()
-                        .newDocument() );
+                XMLHelper.newDocumentBuilder().newDocument() );
     }
 
     /**
index a398e8e024f4f555cdb32b21566c0e4eb811fb56..cdf362acc92b354ad0c43550a76a176f10833de5 100644 (file)
 ==================================================================== */
 package org.apache.poi.hssf.converter;
 
-import org.apache.poi.POIDataSamples;
-import org.apache.poi.hssf.usermodel.HSSFWorkbook;
-import org.apache.poi.util.XMLHelper;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
+import static org.junit.Assert.assertNotNull;
 
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
 import java.io.File;
-import java.io.FilenameFilter;
 import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
-import static org.junit.Assert.assertNotNull;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.util.XMLHelper;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
 
 @RunWith(Parameterized.class)
 public class TestExcelConverterSuite
@@ -53,15 +53,7 @@ public class TestExcelConverterSuite
         List<Object[]> files = new ArrayList<>();
         File directory = POIDataSamples.getDocumentInstance().getFile(
                 "../spreadsheet" );
-        for ( final File child : directory.listFiles( new FilenameFilter()
-        {
-            @Override
-            public boolean accept( File dir, String name )
-            {
-                return name.endsWith( ".xls" ) && !failingFiles.contains( name );
-            }
-        } ) )
-        {
+        for ( final File child : directory.listFiles((dir,name) ->  name.endsWith( ".xls" ) && !failingFiles.contains( name ))) {
             files.add(new Object[] { child });
         }
 
@@ -84,16 +76,12 @@ public class TestExcelConverterSuite
         }
 
         ExcelToHtmlConverter excelToHtmlConverter = new ExcelToHtmlConverter(
-                XMLHelper.getDocumentBuilderFactory().newDocumentBuilder().newDocument() );
+                XMLHelper.newDocumentBuilder().newDocument() );
         excelToHtmlConverter.processWorkbook( workbook );
 
         StringWriter stringWriter = new StringWriter();
 
-        Transformer transformer = TransformerFactory.newInstance()
-                .newTransformer();
-        transformer.setOutputProperty( OutputKeys.ENCODING, "utf-8" );
-        transformer.setOutputProperty( OutputKeys.INDENT, "yes" );
-        transformer.setOutputProperty( OutputKeys.METHOD, "xml" );
+        Transformer transformer = XMLHelper.newTransformer();
         transformer.transform(
                 new DOMSource( excelToHtmlConverter.getDocument() ),
                 new StreamResult( stringWriter ) );
@@ -113,7 +101,7 @@ public class TestExcelConverterSuite
         }
 
         ExcelToHtmlConverter excelToHtmlConverter = new ExcelToHtmlConverter(
-                XMLHelper.getDocumentBuilderFactory().newDocumentBuilder().newDocument() );
+                XMLHelper.newDocumentBuilder().newDocument() );
         excelToHtmlConverter.processWorkbook( workbook );
 
         StringWriter stringWriter = new StringWriter();
index 3525ba78b3e26e47cb65a2bb193784545fce7246..1a8d5b8b803df505c1ad83fa858bd48ba32aac3c 100644 (file)
@@ -18,18 +18,18 @@ package org.apache.poi.hwpf.converter;
 
 import static org.junit.Assert.assertNotNull;
 
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
 import java.io.File;
-import java.io.FilenameFilter;
 import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
 import org.apache.poi.POIDataSamples;
 import org.apache.poi.hwpf.HWPFDocumentCore;
 import org.apache.poi.util.XMLHelper;
@@ -55,15 +55,7 @@ public class TestWordToConverterSuite
         List<Object[]> files = new ArrayList<>();
         File directory = POIDataSamples.getDocumentInstance().getFile(
                 "../document" );
-        for ( final File child : directory.listFiles( new FilenameFilter()
-        {
-            @Override
-            public boolean accept( File dir, String name )
-            {
-                return name.endsWith( ".doc" ) && !failingFiles.contains( name );
-            }
-        } ) )
-        {
+        for ( final File child : directory.listFiles((dir,name) -> name.endsWith( ".doc" ) && !failingFiles.contains( name ))) {
             files.add(new Object[] { child });
         }
 
@@ -83,15 +75,12 @@ public class TestWordToConverterSuite
         }
 
         WordToFoConverter wordToFoConverter = new WordToFoConverter(
-                XMLHelper.getDocumentBuilderFactory().newDocumentBuilder().newDocument() );
+                XMLHelper.newDocumentBuilder().newDocument() );
         wordToFoConverter.processDocument( hwpfDocument );
 
         StringWriter stringWriter = new StringWriter();
 
-        Transformer transformer = TransformerFactory.newInstance()
-                .newTransformer();
-        transformer.setOutputProperty( OutputKeys.ENCODING, "utf-8" );
-        transformer.setOutputProperty( OutputKeys.INDENT, "false" );
+        Transformer transformer = XMLHelper.newTransformer();
         transformer.transform(
                 new DOMSource( wordToFoConverter.getDocument() ),
                 new StreamResult( stringWriter ) );
@@ -111,7 +100,7 @@ public class TestWordToConverterSuite
         }
 
         WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(
-                XMLHelper.getDocumentBuilderFactory().newDocumentBuilder().newDocument() );
+                XMLHelper.newDocumentBuilder().newDocument() );
         wordToHtmlConverter.processDocument( hwpfDocument );
 
         StringWriter stringWriter = new StringWriter();
@@ -140,7 +129,7 @@ public class TestWordToConverterSuite
         }
 
         WordToTextConverter wordToTextConverter = new WordToTextConverter(
-                XMLHelper.getDocumentBuilderFactory().newDocumentBuilder().newDocument() );
+                XMLHelper.newDocumentBuilder().newDocument() );
         wordToTextConverter.processDocument( wordDocument );
 
         StringWriter stringWriter = new StringWriter();
index cd8ced23c988ba87a01e1035ec3fc1b3169237de..54970dce8a223d1c5992df511e35ce86959e8a03 100644 (file)
@@ -22,9 +22,7 @@ import static org.apache.poi.POITestCase.assertContains;
 
 import java.io.StringWriter;
 
-import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
 
@@ -45,14 +43,12 @@ public class TestWordToFoConverter
                 .getDocumentInstance().openResourceAsStream( sampleFileName ) );
 
         WordToFoConverter wordToFoConverter = new WordToFoConverter(
-                XMLHelper.getDocumentBuilderFactory().newDocumentBuilder().newDocument() );
+                XMLHelper.newDocumentBuilder().newDocument() );
         wordToFoConverter.processDocument( hwpfDocument );
 
         StringWriter stringWriter = new StringWriter();
 
-        Transformer transformer = TransformerFactory.newInstance()
-                .newTransformer();
-        transformer.setOutputProperty( OutputKeys.INDENT, "yes" );
+        Transformer transformer = XMLHelper.newTransformer();
         transformer.transform(
                 new DOMSource( wordToFoConverter.getDocument() ),
                 new StreamResult( stringWriter ) );
index b1884f748df2fb049ce61cfe00d6878307108964..673ac681633f7bd08eb0298dc68c4bedd9bda105 100644 (file)
 ==================================================================== */
 package org.apache.poi.hwpf.converter;
 
-import org.apache.poi.POIDataSamples;
-import org.apache.poi.hwpf.HWPFDocument;
-import org.apache.poi.util.XMLHelper;
-import org.junit.Test;
-import org.w3c.dom.Document;
+import static org.apache.poi.POITestCase.assertContains;
+import static org.junit.Assert.assertFalse;
+
+import java.io.StringWriter;
 
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.dom.DOMSource;
 import javax.xml.transform.stream.StreamResult;
-import java.io.StringWriter;
 
-import static org.apache.poi.POITestCase.assertContains;
-import static org.junit.Assert.assertFalse;
+import org.apache.poi.POIDataSamples;
+import org.apache.poi.hwpf.HWPFDocument;
+import org.apache.poi.util.XMLHelper;
+import org.junit.Test;
+import org.w3c.dom.Document;
 
 /**
  * Test cases for {@link WordToHtmlConverter}
@@ -45,7 +45,7 @@ public class TestWordToHtmlConverter {
         HWPFDocument hwpfDocument = new HWPFDocument(POIDataSamples
                 .getDocumentInstance().openResourceAsStream(sampleFileName));
 
-        Document newDocument = XMLHelper.getDocumentBuilderFactory().newDocumentBuilder().newDocument();
+        Document newDocument = XMLHelper.newDocumentBuilder().newDocument();
         WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(
                 newDocument);
 
@@ -58,10 +58,7 @@ public class TestWordToHtmlConverter {
 
         StringWriter stringWriter = new StringWriter();
 
-        Transformer transformer = TransformerFactory.newInstance()
-                .newTransformer();
-        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
-        transformer.setOutputProperty(OutputKeys.ENCODING, "utf-8");
+        Transformer transformer = XMLHelper.newTransformer();
         transformer.setOutputProperty(OutputKeys.METHOD, "html");
         transformer.transform(
                 new DOMSource(wordToHtmlConverter.getDocument()),
index 09c6c64b3328b907a018f610e66585a25c052828..e0a0671c77c8bbeb84c6efb9b51c6f02f6164357 100644 (file)
@@ -899,7 +899,7 @@ public class TestBugs{
     @Test
     public void test59322() throws Exception {
         try(HWPFDocument doc = HWPFTestDataSamples.openSampleFile("59322.doc")) {
-            Document document = XMLHelper.getDocumentBuilderFactory().newDocumentBuilder().newDocument();
+            Document document = XMLHelper.newDocumentBuilder().newDocument();
             WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(document);
             wordToHtmlConverter.processDocument(doc);
             assertNotNull(document);
diff --git a/src/testcases/org/apache/poi/util/TestStaxHelper.java b/src/testcases/org/apache/poi/util/TestStaxHelper.java
deleted file mode 100644 (file)
index 9b781fd..0000000
+++ /dev/null
@@ -1,64 +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.util;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLOutputFactory;
-import javax.xml.stream.XMLStreamException;
-
-import org.junit.Test;
-
-/**
- * Unit test for StaxHelper
- */
-public class TestStaxHelper {
-
-    /**
-     * test that newXMLInputFactory returns a factory with sensible defaults
-     */
-    @Test
-    public void testNewXMLInputFactory() throws XMLStreamException {
-        XMLInputFactory factory = StaxHelper.newXMLInputFactory();
-        assertEquals(true, factory.getProperty(XMLInputFactory.IS_NAMESPACE_AWARE));
-        assertEquals(false, factory.getProperty(XMLInputFactory.IS_VALIDATING));
-        assertEquals(false, factory.getProperty(XMLInputFactory.SUPPORT_DTD));
-        assertEquals(false, factory.getProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES));
-    }
-
-    /**
-     * test that newXMLOutputFactory returns a factory with sensible defaults
-     */
-    @Test
-    public void testNewXMLOutputFactory() {
-        XMLOutputFactory factory = StaxHelper.newXMLOutputFactory();
-        assertEquals(true, factory.getProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES));
-    }
-
-    /**
-     * test that newXMLEventFactory returns a factory
-     */
-    @Test
-    public void testNewXMLEventFactory() {
-        assertNotNull(StaxHelper.newXMLEventFactory());
-    }
-
-}
-
diff --git a/src/testcases/org/apache/poi/util/TestXMLHelper.java b/src/testcases/org/apache/poi/util/TestXMLHelper.java
new file mode 100644 (file)
index 0000000..5536168
--- /dev/null
@@ -0,0 +1,161 @@
+/* ====================================================================
+   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.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+
+import org.junit.Test;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.XMLReader;
+
+public class TestXMLHelper {
+    @Test
+    public void testDocumentBuilder() throws Exception {
+        DocumentBuilder documentBuilder = XMLHelper.newDocumentBuilder();
+        assertNotSame(documentBuilder, XMLHelper.newDocumentBuilder());
+        assertTrue(documentBuilder.isNamespaceAware());
+        assertFalse(documentBuilder.isValidating());
+        documentBuilder.parse(new InputSource(new ByteArrayInputStream("<xml></xml>".getBytes(StandardCharsets.UTF_8))));
+    }
+
+    @Test
+    public void testCreatingManyDocumentBuilders() throws Exception {
+        int limit = 1000;
+        ArrayList<CompletableFuture<DocumentBuilder>> futures = new ArrayList<>();
+        for (int i = 0; i < limit; i++) {
+            futures.add(CompletableFuture.supplyAsync(XMLHelper::newDocumentBuilder));
+        }
+        HashSet<DocumentBuilder> dbs = new HashSet<>();
+        for (CompletableFuture<DocumentBuilder> future : futures) {
+            DocumentBuilder documentBuilder = future.get(10, TimeUnit.SECONDS);
+            assertTrue(documentBuilder.isNamespaceAware());
+            dbs.add(documentBuilder);
+        }
+        assertEquals(limit, dbs.size());
+    }
+
+    @Test
+    public void testDocumentBuilderFactory() throws Exception {
+        try {
+            DocumentBuilderFactory dbf = XMLHelper.getDocumentBuilderFactory();
+            assertTrue(dbf.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING));
+            assertTrue(dbf.getFeature(XMLHelper.FEATURE_DISALLOW_DOCTYPE_DECL));
+            assertFalse(dbf.getFeature(XMLHelper.FEATURE_LOAD_DTD_GRAMMAR));
+            assertFalse(dbf.getFeature(XMLHelper.FEATURE_LOAD_EXTERNAL_DTD));
+        } catch (AbstractMethodError e) {
+            // ignore exceptions from old parsers that don't support this API (https://bz.apache.org/bugzilla/show_bug.cgi?id=62692)
+        }
+    }
+
+    @Test
+    public void testXMLReader() throws Exception {
+        XMLReader reader = XMLHelper.newXMLReader();
+        assertNotSame(reader, XMLHelper.newXMLReader());
+        try {
+            assertTrue(reader.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING));
+            assertFalse(reader.getFeature(XMLHelper.FEATURE_LOAD_DTD_GRAMMAR));
+            assertFalse(reader.getFeature(XMLHelper.FEATURE_LOAD_EXTERNAL_DTD));
+            // assertEquals(XMLHelper.IGNORING_ENTITY_RESOLVER, reader.getEntityResolver());
+            assertNotNull(reader.getProperty(XMLHelper.PROPERTY_ENTITY_EXPANSION_LIMIT));
+            assertEquals("1", reader.getProperty(XMLHelper.PROPERTY_ENTITY_EXPANSION_LIMIT));
+            assertNotNull(reader.getProperty(XMLHelper.PROPERTY_SECURITY_MANAGER));
+        } catch (SAXNotRecognizedException e) {
+            // ignore exceptions from old parsers that don't support these features
+            // (https://bz.apache.org/bugzilla/show_bug.cgi?id=62692)
+        }
+        reader.parse(new InputSource(new ByteArrayInputStream("<xml></xml>".getBytes(StandardCharsets.UTF_8))));
+    }
+
+    @Test
+    public void testCreatingManyXMLReaders() throws Exception {
+        int limit = 1000;
+        ArrayList<CompletableFuture<XMLReader>> futures = new ArrayList<>();
+        for (int i = 0; i < limit; i++) {
+            futures.add(CompletableFuture.supplyAsync(() -> {
+                try {
+                    return XMLHelper.newXMLReader();
+                } catch (RuntimeException e) {
+                    throw e;
+                } catch (Exception e) {
+                    throw new RuntimeException(e);
+                }
+            }));
+        }
+        HashSet<XMLReader> readers = new HashSet<>();
+        for (CompletableFuture<XMLReader> future : futures) {
+            XMLReader reader = future.get(10, TimeUnit.SECONDS);
+            try {
+                assertTrue(reader.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING));
+            } catch (SAXNotRecognizedException e) {
+                // can happen for older XML Parsers, e.g. we have a CI Job which runs with Xerces XML Parser
+                assertTrue("Had Exception about not-recognized SAX feature: " + e + " which is only expected" +
+                                   " for Xerces XML Parser, but had parser: " + reader,
+                           reader.getClass().getName().contains("org.apache.xerces"));
+            }
+            readers.add(reader);
+        }
+        assertEquals(limit, readers.size());
+    }
+
+    /**
+     * test that newXMLInputFactory returns a factory with sensible defaults
+     */
+    @Test
+    public void testNewXMLInputFactory() {
+        XMLInputFactory factory = XMLHelper.newXMLInputFactory();
+        assertTrue((boolean)factory.getProperty(XMLInputFactory.IS_NAMESPACE_AWARE));
+        assertFalse((boolean)factory.getProperty(XMLInputFactory.IS_VALIDATING));
+        assertFalse((boolean)factory.getProperty(XMLInputFactory.SUPPORT_DTD));
+        assertFalse((boolean)factory.getProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES));
+    }
+
+    /**
+     * test that newXMLOutputFactory returns a factory with sensible defaults
+     */
+    @Test
+    public void testNewXMLOutputFactory() {
+        XMLOutputFactory factory = XMLHelper.newXMLOutputFactory();
+        assertTrue((boolean)factory.getProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES));
+    }
+
+    /**
+     * test that newXMLEventFactory returns a factory
+     */
+    @Test
+    public void testNewXMLEventFactory() {
+        assertNotNull(XMLHelper.newXMLEventFactory());
+    }
+}