462 lines
16 KiB
Diff
462 lines
16 KiB
Diff
From a8ecfd058a46a00ea76624a516b6def793c53821 Mon Sep 17 00:00:00 2001
|
|
From: PJ Fanning <fanningpj@apache.org>
|
|
Date: Sat, 26 May 2018 08:31:14 +0000
|
|
Subject: [PATCH] fix build and bring in fixes from
|
|
https://github.com/pjfanning/xmlbeans/blob/trunk/CHANGES.txt
|
|
|
|
[Part of 3.0.0 backport of
|
|
https://github.com/apache/xmlbeans/commit/a8ecfd0]
|
|
|
|
---
|
|
.../xmlbeans/impl/store/NullLogger.java | 81 ++++++++++++
|
|
.../apache/xmlbeans/impl/store/SAXHelper.java | 99 +++++++++++++++
|
|
.../xmlbeans/impl/store/XBLogFactory.java | 119 ++++++++++++++++++
|
|
.../apache/xmlbeans/impl/store/XBLogger.java | 115 +++++++++++++++++
|
|
4 files changed, 414 insertions(+)
|
|
create mode 100644 src/store/org/apache/xmlbeans/impl/store/NullLogger.java
|
|
create mode 100644 src/store/org/apache/xmlbeans/impl/store/SAXHelper.java
|
|
create mode 100644 src/store/org/apache/xmlbeans/impl/store/XBLogFactory.java
|
|
create mode 100644 src/store/org/apache/xmlbeans/impl/store/XBLogger.java
|
|
|
|
diff --git a/src/store/org/apache/xmlbeans/impl/store/NullLogger.java b/src/store/org/apache/xmlbeans/impl/store/NullLogger.java
|
|
new file mode 100644
|
|
index 00000000..aca8d1d5
|
|
--- /dev/null
|
|
+++ b/src/store/org/apache/xmlbeans/impl/store/NullLogger.java
|
|
@@ -0,0 +1,81 @@
|
|
+/* Copyright 2017 The Apache Software Foundation
|
|
+ *
|
|
+ * Licensed 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.xmlbeans.impl.store;
|
|
+
|
|
+/**
|
|
+ * A logger class that strives to make it as easy as possible for
|
|
+ * developers to write log calls, while simultaneously making those
|
|
+ * calls as cheap as possible by performing lazy evaluation of the log
|
|
+ * message.<p>
|
|
+ */
|
|
+public class NullLogger extends XBLogger {
|
|
+ @Override
|
|
+ public void initialize(final String cat) {
|
|
+ // do nothing
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Log a message
|
|
+ *
|
|
+ * @param level One of DEBUG, INFO, WARN, ERROR, FATAL
|
|
+ * @param obj1 The object to log.
|
|
+ */
|
|
+
|
|
+ @Override
|
|
+ protected void _log(final int level, final Object obj1) {
|
|
+ // do nothing
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Log a message
|
|
+ *
|
|
+ * @param level One of DEBUG, INFO, WARN, ERROR, FATAL
|
|
+ * @param obj1 The object to log. This is converted to a string.
|
|
+ * @param exception An exception to be logged
|
|
+ */
|
|
+ @Override
|
|
+ protected void _log(int level, Object obj1, final Throwable exception) {
|
|
+ // do nothing
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Log a message. Lazily appends Object parameters together.
|
|
+ * If the last parameter is a {@link Throwable} it is logged specially.
|
|
+ *
|
|
+ * @param level One of DEBUG, INFO, WARN, ERROR, FATAL
|
|
+ * @param objs the objects to place in the message
|
|
+ */
|
|
+ @Override
|
|
+ public void log(int level, Object... objs) {
|
|
+ // do nothing
|
|
+ }
|
|
+
|
|
+
|
|
+ /**
|
|
+ * Check if a logger is enabled to log at the specified level
|
|
+ *
|
|
+ * @param level One of DEBUG, INFO, WARN, ERROR, FATAL
|
|
+ */
|
|
+ @Override
|
|
+ public boolean check(final int level) {
|
|
+ return false;
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+
|
|
+
|
|
diff --git a/src/store/org/apache/xmlbeans/impl/store/SAXHelper.java b/src/store/org/apache/xmlbeans/impl/store/SAXHelper.java
|
|
new file mode 100644
|
|
index 00000000..67fb3a0e
|
|
--- /dev/null
|
|
+++ b/src/store/org/apache/xmlbeans/impl/store/SAXHelper.java
|
|
@@ -0,0 +1,99 @@
|
|
+/* Copyright 2017 The Apache Software Foundation
|
|
+ *
|
|
+ * Licensed 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.xmlbeans.impl.store;
|
|
+
|
|
+import java.io.IOException;
|
|
+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.xml.sax.EntityResolver;
|
|
+import org.xml.sax.InputSource;
|
|
+import org.xml.sax.SAXException;
|
|
+import org.xml.sax.XMLReader;
|
|
+
|
|
+/**
|
|
+ * Provides handy methods for working with SAX parsers and readers
|
|
+ */
|
|
+public final class SAXHelper {
|
|
+ private static final XBLogger logger = XBLogFactory.getLogger(SAXHelper.class);
|
|
+ private static long lastLog;
|
|
+
|
|
+ private SAXHelper() {}
|
|
+
|
|
+ /**
|
|
+ * Creates a new SAX XMLReader, with sensible defaults
|
|
+ */
|
|
+ public static synchronized 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 = new EntityResolver() {
|
|
+ @Override
|
|
+ public InputSource resolveEntity(String publicId, String systemId)
|
|
+ throws SAXException, IOException {
|
|
+ return new InputSource(new StringReader(""));
|
|
+ }
|
|
+ };
|
|
+
|
|
+ private static final SAXParserFactory saxFactory;
|
|
+ static {
|
|
+ saxFactory = SAXParserFactory.newInstance();
|
|
+ saxFactory.setValidating(false);
|
|
+ saxFactory.setNamespaceAware(true);
|
|
+ }
|
|
+
|
|
+ private static void trySetSAXFeature(XMLReader xmlReader, String feature) {
|
|
+ try {
|
|
+ xmlReader.setFeature(feature, true);
|
|
+ } catch (Exception e) {
|
|
+ logger.log(XBLogger.WARN, "SAX Feature unsupported", feature, e);
|
|
+ } catch (AbstractMethodError ame) {
|
|
+ logger.log(XBLogger.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, 4096);
|
|
+ xmlReader.setProperty("http://apache.org/xml/properties/security-manager", mgr);
|
|
+ // Stop once one can be setup without error
|
|
+ return;
|
|
+ } 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(XBLogger.WARN, "SAX Security Manager could not be setup [log suppressed for 5 minutes]", e);
|
|
+ lastLog = System.currentTimeMillis();
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/store/org/apache/xmlbeans/impl/store/XBLogFactory.java b/src/store/org/apache/xmlbeans/impl/store/XBLogFactory.java
|
|
new file mode 100644
|
|
index 00000000..f31d4db7
|
|
--- /dev/null
|
|
+++ b/src/store/org/apache/xmlbeans/impl/store/XBLogFactory.java
|
|
@@ -0,0 +1,119 @@
|
|
+/* Copyright 2017 The Apache Software Foundation
|
|
+ *
|
|
+ * Licensed 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.xmlbeans.impl.store;
|
|
+
|
|
+import java.util.HashMap;
|
|
+import java.util.Map;
|
|
+
|
|
+/**
|
|
+ * Provides logging without clients having to mess with
|
|
+ * configuration/initialization.
|
|
+ *
|
|
+ * @author Andrew C. Oliver (acoliver at apache dot org)
|
|
+ * @author Marc Johnson (mjohnson at apache dot org)
|
|
+ * @author Nicola Ken Barozzi (nicolaken at apache.org)
|
|
+ */
|
|
+public final class XBLogFactory {
|
|
+ /**
|
|
+ * Map of XBLogger instances, with classes as keys
|
|
+ */
|
|
+ private static final Map<String,XBLogger> _loggers = new HashMap<String,XBLogger>();
|
|
+
|
|
+ /**
|
|
+ * A common instance of NullLogger, as it does nothing
|
|
+ * we only need the one
|
|
+ */
|
|
+ private static final XBLogger _nullLogger = new NullLogger();
|
|
+ /**
|
|
+ * The name of the class to use. Initialised the
|
|
+ * first time we need it
|
|
+ */
|
|
+ static String _loggerClassName = null;
|
|
+
|
|
+ /**
|
|
+ * Construct a XBLogFactory.
|
|
+ */
|
|
+ private XBLogFactory() {}
|
|
+
|
|
+ /**
|
|
+ * Get a logger, based on a class name
|
|
+ *
|
|
+ * @param theclass the class whose name defines the log
|
|
+ *
|
|
+ * @return a XBLogger for the specified class
|
|
+ */
|
|
+ public static XBLogger getLogger(final Class<?> theclass) {
|
|
+ return getLogger(theclass.getName());
|
|
+ }
|
|
+
|
|
+ /**
|
|
+ * Get a logger, based on a String
|
|
+ *
|
|
+ * @param cat the String that defines the log
|
|
+ *
|
|
+ * @return a XBLogger for the specified class
|
|
+ */
|
|
+ public static XBLogger getLogger(final String cat) {
|
|
+ // If we haven't found out what logger to use yet,
|
|
+ // then do so now
|
|
+ // Don't look it up until we're first asked, so
|
|
+ // that our users can set the system property
|
|
+ // between class loading and first use
|
|
+ if(_loggerClassName == null) {
|
|
+ try {
|
|
+ _loggerClassName = System.getProperty("org.apache.xmlbeans.impl.store.XBLogger");
|
|
+ } catch(Exception e) {
|
|
+ // ignore any exception here
|
|
+ }
|
|
+
|
|
+ // Use the default logger if none specified,
|
|
+ // or none could be fetched
|
|
+ if(_loggerClassName == null) {
|
|
+ _loggerClassName = _nullLogger.getClass().getName();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ // Short circuit for the null logger, which
|
|
+ // ignores all categories
|
|
+ if(_loggerClassName.equals(_nullLogger.getClass().getName())) {
|
|
+ return _nullLogger;
|
|
+ }
|
|
+
|
|
+
|
|
+ // Fetch the right logger for them, creating
|
|
+ // it if that's required
|
|
+ XBLogger logger = _loggers.get(cat);
|
|
+ if (logger == null) {
|
|
+ try {
|
|
+ @SuppressWarnings("unchecked")
|
|
+ Class<? extends XBLogger> loggerClass =
|
|
+ (Class<? extends XBLogger>) Class.forName(_loggerClassName);
|
|
+ logger = loggerClass.newInstance();
|
|
+ logger.initialize(cat);
|
|
+ } catch(Exception e) {
|
|
+ // Give up and use the null logger
|
|
+ logger = _nullLogger;
|
|
+ _loggerClassName = _nullLogger.getClass().getName();
|
|
+ }
|
|
+
|
|
+ // Save for next time
|
|
+ _loggers.put(cat, logger);
|
|
+ }
|
|
+ return logger;
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
diff --git a/src/store/org/apache/xmlbeans/impl/store/XBLogger.java b/src/store/org/apache/xmlbeans/impl/store/XBLogger.java
|
|
new file mode 100644
|
|
index 00000000..fa605112
|
|
--- /dev/null
|
|
+++ b/src/store/org/apache/xmlbeans/impl/store/XBLogger.java
|
|
@@ -0,0 +1,115 @@
|
|
+/* Copyright 2017 The Apache Software Foundation
|
|
+ *
|
|
+ * Licensed 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.xmlbeans.impl.store;
|
|
+
|
|
+/**
|
|
+ * A logger interface that strives to make it as easy as possible for
|
|
+ * developers to write log calls, while simultaneously making those
|
|
+ * calls as cheap as possible by performing lazy evaluation of the log
|
|
+ * message.<p>
|
|
+ */
|
|
+public abstract class XBLogger {
|
|
+
|
|
+ public static final int DEBUG = 1;
|
|
+ public static final int INFO = 3;
|
|
+ public static final int WARN = 5;
|
|
+ public static final int ERROR = 7;
|
|
+ public static final int FATAL = 9;
|
|
+
|
|
+ /** Short strings for numeric log level. Use level as array index. */
|
|
+ protected static final String LEVEL_STRINGS_SHORT[] = {"?", "D", "?", "I", "?", "W", "?", "E", "?", "F", "?"};
|
|
+ /** Long strings for numeric log level. Use level as array index. */
|
|
+ protected static final String LEVEL_STRINGS[] = {"?0?", "DEBUG", "?2?", "INFO", "?4?", "WARN", "?6?", "ERROR", "?8?", "FATAL", "?10+?"};
|
|
+
|
|
+
|
|
+ /**
|
|
+ * package scope so it cannot be instantiated outside of the util
|
|
+ * package. You need a XBLogger? Go to the XBLogFactory for one
|
|
+ */
|
|
+ XBLogger() {
|
|
+ // no fields to initialize
|
|
+ }
|
|
+
|
|
+ abstract public void initialize(String cat);
|
|
+
|
|
+ /**
|
|
+ * Log a message
|
|
+ *
|
|
+ * @param level One of DEBUG, INFO, WARN, ERROR, FATAL
|
|
+ * @param obj1 The object to log. This is converted to a string.
|
|
+ */
|
|
+ abstract protected void _log(int level, Object obj1);
|
|
+
|
|
+ /**
|
|
+ * Log a message
|
|
+ *
|
|
+ * @param level One of DEBUG, INFO, WARN, ERROR, FATAL
|
|
+ * @param obj1 The object to log. This is converted to a string.
|
|
+ * @param exception An exception to be logged
|
|
+ */
|
|
+ abstract protected void _log(int level, Object obj1, final Throwable exception);
|
|
+
|
|
+
|
|
+ /**
|
|
+ * Check if a logger is enabled to log at the specified level
|
|
+ * This allows code to avoid building strings or evaluating functions in
|
|
+ * the arguments to log.
|
|
+ *
|
|
+ * An example:
|
|
+ * <code><pre>
|
|
+ * if (logger.check(XBLogger.INFO)) {
|
|
+ * logger.log(XBLogger.INFO, "Avoid concatenating " + " strings and evaluating " + functions());
|
|
+ * }
|
|
+ * </pre></code>
|
|
+ *
|
|
+ * @param level One of DEBUG, INFO, WARN, ERROR, FATAL
|
|
+ */
|
|
+ abstract public boolean check(int level);
|
|
+
|
|
+ /**
|
|
+ * Log a message. Lazily appends Object parameters together.
|
|
+ * If the last parameter is a {@link Throwable} it is logged specially.
|
|
+ *
|
|
+ * @param level One of DEBUG, INFO, WARN, ERROR, FATAL
|
|
+ * @param objs the objects to place in the message
|
|
+ */
|
|
+ public void log(int level, Object... objs) {
|
|
+ if (!check(level)) return;
|
|
+ StringBuilder sb = new StringBuilder(32);
|
|
+ Throwable lastEx = null;
|
|
+ for (int i=0; i<objs.length; i++) {
|
|
+ if (i == objs.length-1 && objs[i] instanceof Throwable) {
|
|
+ lastEx = (Throwable)objs[i];
|
|
+ } else {
|
|
+ sb.append(objs[i]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ String msg = sb.toString();
|
|
+ msg = msg.replaceAll("[\r\n]+", " "); // log forging escape
|
|
+
|
|
+ // somehow this ambiguity works and doesn't lead to a loop,
|
|
+ // but it's confusing ...
|
|
+ if (lastEx == null) {
|
|
+ _log(level, msg);
|
|
+ } else {
|
|
+ _log(level, msg, lastEx);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
--
|
|
2.23.0
|
|
|