From 08159e66a738c291572745cee8cc3617777dc2b5 Mon Sep 17 00:00:00 2001 From: Andreas Beeker Date: Tue, 3 Dec 2019 21:56:47 +0000 Subject: [PATCH] Sonar Fixes + Refactor scattered XML initializations to XMLHelper git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1870769 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/xssf/eventusermodel/XLSX2CSV.java | 4 +- .../eventusermodel/examples/FromHowTo.java | 6 +- .../poi/sl/draw/geom/PresetGeometries.java | 4 +- src/java/org/apache/poi/util/StaxHelper.java | 33 +-- src/java/org/apache/poi/util/XMLHelper.java | 279 +++++++++++++++++- .../poi/ooxml/dev/OOXMLPrettyPrint.java | 37 ++- .../apache/poi/ooxml/util/DocumentHelper.java | 125 +------- .../poi/ooxml/util/POIXMLConstants.java | 26 -- .../org/apache/poi/ooxml/util/SAXHelper.java | 107 +------ .../poi/ooxml/util/TransformerHelper.java | 31 +- .../poi/openxml4j/opc/StreamHelper.java | 17 +- .../dsig/services/TSPTimeStampService.java | 2 +- .../ReadOnlySharedStringsTable.java | 7 +- .../poi/xssf/eventusermodel/XSSFReader.java | 7 +- .../XSSFEventBasedExcelExtractor.java | 12 +- .../poi/xssf/extractor/XSSFExportToXml.java | 12 +- .../xssf/usermodel/XSSFBuiltinTableStyle.java | 17 +- .../poi/ooxml/util/TestDocumentHelper.java | 73 ----- .../apache/poi/ooxml/util/TestSAXHelper.java | 85 ------ .../poi/openxml4j/opc/TestContentType.java | 22 +- .../xssf/extractor/TestXSSFExportToXML.java | 24 +- .../poi/xssf/usermodel/TestXSSFBugs.java | 31 +- .../hssf/converter/ExcelToFoConverter.java | 11 +- .../hssf/converter/ExcelToHtmlConverter.java | 9 +- .../poi/hwpf/converter/WordToFoConverter.java | 9 +- .../hwpf/converter/WordToHtmlConverter.java | 8 +- .../hwpf/converter/WordToTextConverter.java | 12 +- .../converter/TestExcelConverterSuite.java | 46 ++- .../converter/TestWordToConverterSuite.java | 33 +-- .../hwpf/converter/TestWordToFoConverter.java | 8 +- .../converter/TestWordToHtmlConverter.java | 25 +- .../apache/poi/hwpf/usermodel/TestBugs.java | 2 +- .../org/apache/poi/util/TestStaxHelper.java | 64 ---- .../org/apache/poi/util/TestXMLHelper.java | 161 ++++++++++ 34 files changed, 593 insertions(+), 756 deletions(-) delete mode 100644 src/ooxml/java/org/apache/poi/ooxml/util/POIXMLConstants.java delete mode 100644 src/ooxml/testcases/org/apache/poi/ooxml/util/TestDocumentHelper.java delete mode 100644 src/ooxml/testcases/org/apache/poi/ooxml/util/TestSAXHelper.java delete mode 100644 src/testcases/org/apache/poi/util/TestStaxHelper.java create mode 100644 src/testcases/org/apache/poi/util/TestXMLHelper.java diff --git a/src/examples/src/org/apache/poi/xssf/eventusermodel/XLSX2CSV.java b/src/examples/src/org/apache/poi/xssf/eventusermodel/XLSX2CSV.java index 0ed52e9b5f..85300de6f4 100644 --- a/src/examples/src/org/apache/poi/xssf/eventusermodel/XLSX2CSV.java +++ b/src/examples/src/org/apache/poi/xssf/eventusermodel/XLSX2CSV.java @@ -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); diff --git a/src/examples/src/org/apache/poi/xssf/eventusermodel/examples/FromHowTo.java b/src/examples/src/org/apache/poi/xssf/eventusermodel/examples/FromHowTo.java index cbb7990c5d..f45cac0a91 100644 --- a/src/examples/src/org/apache/poi/xssf/eventusermodel/examples/FromHowTo.java +++ b/src/examples/src/org/apache/poi/xssf/eventusermodel/examples/FromHowTo.java @@ -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; diff --git a/src/java/org/apache/poi/sl/draw/geom/PresetGeometries.java b/src/java/org/apache/poi/sl/draw/geom/PresetGeometries.java index c010defc0b..98b2d58fa3 100644 --- a/src/java/org/apache/poi/sl/draw/geom/PresetGeometries.java +++ b/src/java/org/apache/poi/sl/draw/geom/PresetGeometries.java @@ -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 { @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: diff --git a/src/java/org/apache/poi/util/StaxHelper.java b/src/java/org/apache/poi/util/StaxHelper.java index 1ce05b9eff..e612d92e7f 100644 --- a/src/java/org/apache/poi/util/StaxHelper.java +++ b/src/java/org/apache/poi/util/StaxHelper.java @@ -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 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(); } } diff --git a/src/java/org/apache/poi/util/XMLHelper.java b/src/java/org/apache/poi/util/XMLHelper.java index 9c29546eba..fd02caca2f 100644 --- a/src/java/org/apache/poi/util/XMLHelper.java +++ b/src/java/org/apache/poi/util/XMLHelper.java @@ -17,19 +17,71 @@ 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("")); } } diff --git a/src/ooxml/java/org/apache/poi/ooxml/dev/OOXMLPrettyPrint.java b/src/ooxml/java/org/apache/poi/ooxml/dev/OOXMLPrettyPrint.java index 8e8b9571d1..fd48c05462 100644 --- a/src/ooxml/java/org/apache/poi/ooxml/dev/OOXMLPrettyPrint.java +++ b/src/ooxml/java/org/apache/poi/ooxml/dev/OOXMLPrettyPrint.java @@ -16,24 +16,33 @@ ==================================================================== */ 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); diff --git a/src/ooxml/java/org/apache/poi/ooxml/util/DocumentHelper.java b/src/ooxml/java/org/apache/poi/ooxml/util/DocumentHelper.java index 4e66f46b9c..f5a2b13996 100644 --- a/src/ooxml/java/org/apache/poi/ooxml/util/DocumentHelper.java +++ b/src/ooxml/java/org/apache/poi/ooxml/util/DocumentHelper.java @@ -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 index c6d7935fda..0000000000 --- a/src/ooxml/java/org/apache/poi/ooxml/util/POIXMLConstants.java +++ /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"; -} diff --git a/src/ooxml/java/org/apache/poi/ooxml/util/SAXHelper.java b/src/ooxml/java/org/apache/poi/ooxml/util/SAXHelper.java index ede0ac4582..a6c2b58485 100644 --- a/src/ooxml/java/org/apache/poi/ooxml/util/SAXHelper.java +++ b/src/ooxml/java/org/apache/poi/ooxml/util/SAXHelper.java @@ -17,120 +17,25 @@ 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(); } } diff --git a/src/ooxml/java/org/apache/poi/ooxml/util/TransformerHelper.java b/src/ooxml/java/org/apache/poi/ooxml/util/TransformerHelper.java index 37422c6c91..e6a3f0c8f3 100644 --- a/src/ooxml/java/org/apache/poi/ooxml/util/TransformerHelper.java +++ b/src/ooxml/java/org/apache/poi/ooxml/util/TransformerHelper.java @@ -17,33 +17,20 @@ 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(); } } diff --git a/src/ooxml/java/org/apache/poi/openxml4j/opc/StreamHelper.java b/src/ooxml/java/org/apache/poi/openxml4j/opc/StreamHelper.java index 3c4dc6a238..af31eb3ab3 100644 --- a/src/ooxml/java/org/apache/poi/openxml4j/opc/StreamHelper.java +++ b/src/ooxml/java/org/apache/poi/openxml4j/opc/StreamHelper.java @@ -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; } } diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TSPTimeStampService.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TSPTimeStampService.java index ec6a3f0e2d..c7fd85c468 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TSPTimeStampService.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/services/TSPTimeStampService.java @@ -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 diff --git a/src/ooxml/java/org/apache/poi/xssf/eventusermodel/ReadOnlySharedStringsTable.java b/src/ooxml/java/org/apache/poi/xssf/eventusermodel/ReadOnlySharedStringsTable.java index 09191f9abf..17013e7333 100644 --- a/src/ooxml/java/org/apache/poi/xssf/eventusermodel/ReadOnlySharedStringsTable.java +++ b/src/ooxml/java/org/apache/poi/xssf/eventusermodel/ReadOnlySharedStringsTable.java @@ -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) { diff --git a/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFReader.java b/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFReader.java index 8d1ce1a949..b239951c43 100644 --- a/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFReader.java +++ b/src/ooxml/java/org/apache/poi/xssf/eventusermodel/XSSFReader.java @@ -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); } diff --git a/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFEventBasedExcelExtractor.java b/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFEventBasedExcelExtractor.java index 526812183d..998037b59b 100644 --- a/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFEventBasedExcelExtractor.java +++ b/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFEventBasedExcelExtractor.java @@ -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); diff --git a/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java b/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java index e870349b4d..3904b9fd19 100644 --- a/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java +++ b/src/ooxml/java/org/apache/poi/xssf/extractor/XSSFExportToXml.java @@ -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{ //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{ @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[] 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; diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFBuiltinTableStyle.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFBuiltinTableStyle.java index 36a3840223..2ba065b766 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFBuiltinTableStyle.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFBuiltinTableStyle.java @@ -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 index 3c07f25d5b..0000000000 --- a/src/ooxml/testcases/org/apache/poi/ooxml/util/TestDocumentHelper.java +++ /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("".getBytes(StandardCharsets.UTF_8)))); - } - - @Test - public void testCreatingManyDocumentBuilders() throws Exception { - int limit = 1000; - ArrayList> futures = new ArrayList<>(); - for(int i = 0; i < limit; i++) { - futures.add(CompletableFuture.supplyAsync(DocumentHelper::newDocumentBuilder)); - } - HashSet dbs = new HashSet<>(); - for(CompletableFuture 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 index 536194dea4..0000000000 --- a/src/ooxml/testcases/org/apache/poi/ooxml/util/TestSAXHelper.java +++ /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("".getBytes(StandardCharsets.UTF_8)))); - } - - @Test - public void testCreatingManyXMLReaders() throws Exception { - int limit = 1000; - ArrayList> 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 readers = new HashSet<>(); - for(CompletableFuture 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()); - } -} diff --git a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestContentType.java b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestContentType.java index 9050e01a59..3858bc688d 100644 --- a/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestContentType.java +++ b/src/ooxml/testcases/org/apache/poi/openxml4j/opc/TestContentType.java @@ -17,7 +17,15 @@ 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; diff --git a/src/ooxml/testcases/org/apache/poi/xssf/extractor/TestXSSFExportToXML.java b/src/ooxml/testcases/org/apache/poi/xssf/extractor/TestXSSFExportToXML.java index 282f02371e..e0386b860a 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/extractor/TestXSSFExportToXML.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/extractor/TestXSSFExportToXML.java @@ -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("")[1].split("")[0].trim(); String a_b = a.split("")[1].split("")[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")) { diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java index da056eb1ea..9eb2ed9dc7 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java @@ -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"); diff --git a/src/scratchpad/src/org/apache/poi/hssf/converter/ExcelToFoConverter.java b/src/scratchpad/src/org/apache/poi/hssf/converter/ExcelToFoConverter.java index a8d2832240..0bdaf57c65 100644 --- a/src/scratchpad/src/org/apache/poi/hssf/converter/ExcelToFoConverter.java +++ b/src/scratchpad/src/org/apache/poi/hssf/converter/ExcelToFoConverter.java @@ -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 { diff --git a/src/scratchpad/src/org/apache/poi/hssf/converter/ExcelToHtmlConverter.java b/src/scratchpad/src/org/apache/poi/hssf/converter/ExcelToHtmlConverter.java index 2e173e15d4..e3f5e9aaff 100644 --- a/src/scratchpad/src/org/apache/poi/hssf/converter/ExcelToHtmlConverter.java +++ b/src/scratchpad/src/org/apache/poi/hssf/converter/ExcelToHtmlConverter.java @@ -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(); } diff --git a/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToFoConverter.java b/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToFoConverter.java index ad51d4b7cf..9f2bbdba80 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToFoConverter.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToFoConverter.java @@ -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); diff --git a/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToHtmlConverter.java b/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToHtmlConverter.java index 784fb5028c..d3d4f6e57b 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToHtmlConverter.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToHtmlConverter.java @@ -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); diff --git a/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToTextConverter.java b/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToTextConverter.java index 399029233d..3103c81869 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToTextConverter.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToTextConverter.java @@ -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() ); } /** diff --git a/src/scratchpad/testcases/org/apache/poi/hssf/converter/TestExcelConverterSuite.java b/src/scratchpad/testcases/org/apache/poi/hssf/converter/TestExcelConverterSuite.java index a398e8e024..cdf362acc9 100644 --- a/src/scratchpad/testcases/org/apache/poi/hssf/converter/TestExcelConverterSuite.java +++ b/src/scratchpad/testcases/org/apache/poi/hssf/converter/TestExcelConverterSuite.java @@ -16,26 +16,26 @@ ==================================================================== */ 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 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(); diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToConverterSuite.java b/src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToConverterSuite.java index 3525ba78b3..1a8d5b8b80 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToConverterSuite.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToConverterSuite.java @@ -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 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(); diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToFoConverter.java b/src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToFoConverter.java index cd8ced23c9..54970dce8a 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToFoConverter.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToFoConverter.java @@ -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 ) ); diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToHtmlConverter.java b/src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToHtmlConverter.java index b1884f748d..673ac68163 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToHtmlConverter.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/converter/TestWordToHtmlConverter.java @@ -16,21 +16,21 @@ ==================================================================== */ 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()), diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestBugs.java b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestBugs.java index 09c6c64b33..e0a0671c77 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestBugs.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestBugs.java @@ -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 index 9b781fd6fb..0000000000 --- a/src/testcases/org/apache/poi/util/TestStaxHelper.java +++ /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 index 0000000000..5536168545 --- /dev/null +++ b/src/testcases/org/apache/poi/util/TestXMLHelper.java @@ -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("".getBytes(StandardCharsets.UTF_8)))); + } + + @Test + public void testCreatingManyDocumentBuilders() throws Exception { + int limit = 1000; + ArrayList> futures = new ArrayList<>(); + for (int i = 0; i < limit; i++) { + futures.add(CompletableFuture.supplyAsync(XMLHelper::newDocumentBuilder)); + } + HashSet dbs = new HashSet<>(); + for (CompletableFuture 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("".getBytes(StandardCharsets.UTF_8)))); + } + + @Test + public void testCreatingManyXMLReaders() throws Exception { + int limit = 1000; + ArrayList> 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 readers = new HashSet<>(); + for (CompletableFuture 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()); + } +} -- 2.39.5