diff --git a/xmlbeans/CHANGES.txt b/xmlbeans/CHANGES.txt
index 4140cddc33..9afc32488b 100644
--- a/xmlbeans/CHANGES.txt
+++ b/xmlbeans/CHANGES.txt
@@ -1,3 +1,20 @@
+Changes in V2.6.4 since V2.6.3
+
+* Remove Piccolo support
+* Apply XML Entity Expansion security checks
+
+Changes in V2.6.3 since V2.6.2
+
+* ArrayIndexOutOfBoundsException when writing CDATA (https://issues.apache.org/jira/browse/XMLBEANS-404)
+
+Changes in V2.6.2 since V2.6.1
+
+* Duplicate classes in jar (https://issues.apache.org/jira/browse/XMLBEANS-499)
+
+Changes in V2.6.1 since V2.6.0
+
+* Fix for Unicode Surrogate chars being lost when writing XML (https://bz.apache.org/bugzilla/show_bug.cgi?id=54084 & https://issues.apache.org/jira/browse/XMLBEANS-332)
+
Changes in V2.6.0 since V2.5.0
* Add new xml option CopyUseNewSynchronizationDomain used for copy.
diff --git a/xmlbeans/README.md b/xmlbeans/README.md
new file mode 100644
index 0000000000..17453f8544
--- /dev/null
+++ b/xmlbeans/README.md
@@ -0,0 +1,24 @@
+# xmlbeans
+
+[![Build Status](https://travis-ci.org/pjfanning/xmlbeans.svg?branch=trunk)](https://travis-ci.org/pjfanning/xmlbeans)
+[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.github.pjfanning/xmlbeans/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.github.pjfanning/xmlbeans)
+
+Latest source from ```http://svn.apache.org/repos/asf/xmlbeans/trunk/```. Some changes have been made to get the build working.
+
+The core use case is to help users of Apache Poi, which depends on the no longer maintained Apache XMLBeans library.
+
+* Release 2.6.1 includes a fix for an issue where Unicode Surrogate chars were replaced with `?` chars ?when outputting files - https://bz.apache.org/bugzilla/show_bug.cgi?id=54084
+* fixes an issue affecting usage on Android: https://issues.apache.org/jira/browse/XMLBEANS-499
+
+## Sample
+
+https://github.com/pjfanning/poi-xmlbeans-patch-test
+
+## Build
+```
+./xbeanenv.sh
+ant
+ant checkintest
+```
+
+Output jar is found at ```build/lib/xbean.jar```
diff --git a/xmlbeans/build.xml b/xmlbeans/build.xml
index 2505a36dde..e7c27f5316 100644
--- a/xmlbeans/build.xml
+++ b/xmlbeans/build.xml
@@ -15,11 +15,11 @@
-->
-
-
-
+
+
+
-
+
@@ -128,39 +128,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -353,12 +320,8 @@
-
-
-
-
@@ -488,7 +451,7 @@
store.classes, saaj_api.classes,
marshal.classes, xpath.classes, oldxbean.jar, xsdschema.classes,
xmlinputstream.classes, resolver.jar, xbean_xpath.jar,
- piccolo.classes, tools.classes, jamsupport.classes">
+ tools.classes, jamsupport.classes">
@@ -509,7 +472,6 @@
-
@@ -523,10 +485,6 @@
-
-
-
@@ -545,12 +503,10 @@
-
+
-
-
-
+
@@ -586,7 +542,6 @@
-
@@ -597,11 +552,10 @@
-
+
-
@@ -639,7 +593,7 @@
+ configschema.classes, toolschema.classes, jam.classes">
@@ -655,7 +609,6 @@
-
@@ -681,7 +634,6 @@
-
@@ -691,17 +643,17 @@
+
-
+
-
@@ -738,17 +690,15 @@
+ depends="dirs, common.classes, xmlpublic.classes, typestore.classes, saaj_api.classes">
-
-
@@ -756,18 +706,16 @@
-
-
@@ -784,13 +732,11 @@
-
-
@@ -834,7 +780,7 @@
-
+
@@ -919,7 +865,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/xmlbeans/external/lib/piccolo.LICENSE.txt b/xmlbeans/external/lib/piccolo.LICENSE.txt
deleted file mode 100644
index 57bc88a15a..0000000000
--- a/xmlbeans/external/lib/piccolo.LICENSE.txt
+++ /dev/null
@@ -1,202 +0,0 @@
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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.
-
diff --git a/xmlbeans/external/lib/piccolo_apache_dist_20040629.jar b/xmlbeans/external/lib/piccolo_apache_dist_20040629.jar
deleted file mode 100644
index 7113ab63ce..0000000000
Binary files a/xmlbeans/external/lib/piccolo_apache_dist_20040629.jar and /dev/null differ
diff --git a/xmlbeans/external/lib/piccolo_apache_dist_20040629_v2.jar b/xmlbeans/external/lib/piccolo_apache_dist_20040629_v2.jar
deleted file mode 100644
index 66f4e24844..0000000000
Binary files a/xmlbeans/external/lib/piccolo_apache_dist_20040629_v2.jar and /dev/null differ
diff --git a/xmlbeans/external/lib/piccolo_apache_dist_20040711.jar b/xmlbeans/external/lib/piccolo_apache_dist_20040711.jar
deleted file mode 100644
index 4db79cfbd4..0000000000
Binary files a/xmlbeans/external/lib/piccolo_apache_dist_20040711.jar and /dev/null differ
diff --git a/xmlbeans/external/lib/piccolo_apache_dist_20040711_v2.jar b/xmlbeans/external/lib/piccolo_apache_dist_20040711_v2.jar
deleted file mode 100644
index 5e546189a5..0000000000
Binary files a/xmlbeans/external/lib/piccolo_apache_dist_20040711_v2.jar and /dev/null differ
diff --git a/xmlbeans/external/lib/saxonb9-0-0-4j.zip b/xmlbeans/external/lib/saxonb9-0-0-4j.zip
new file mode 100644
index 0000000000..c0cea2481a
Binary files /dev/null and b/xmlbeans/external/lib/saxonb9-0-0-4j.zip differ
diff --git a/xmlbeans/src/store/org/apache/xmlbeans/impl/store/Cur.java b/xmlbeans/src/store/org/apache/xmlbeans/impl/store/Cur.java
index 2a865d31d2..fcb8bfe261 100755
--- a/xmlbeans/src/store/org/apache/xmlbeans/impl/store/Cur.java
+++ b/xmlbeans/src/store/org/apache/xmlbeans/impl/store/Cur.java
@@ -3466,28 +3466,36 @@ final class Cur
String s = CharUtil.getString( src, off, cch );
- for ( int i = 0 ; i < s.length() ; i++ )
+ for ( int i = 0 ; i < s.length(); )
{
- if (i== 36)
+ if (i == 36)
{
o.print( "..." );
break;
}
- char ch = s.charAt( i );
-
- if (ch >= 32 && ch < 127)
- o.print( ch );
- else if (ch == '\n')
- o.print( "\\n" );
- else if (ch == '\r')
- o.print( "\\r" );
- else if (ch == '\t')
- o.print( "\\t" );
- else if (ch == '\"')
- o.print( "\\\"" );
- else
- o.print( "<#" + ((int) ch) + ">" );
+ int codePoint = s.codePointAt( i );
+ char[] chars = Character.toChars(codePoint);
+
+ if ( chars.length == 1 ) {
+ char ch = chars[0];
+ if (ch >= 32 && ch < 127)
+ o.print( ch );
+ else if (ch == '\n')
+ o.print( "\\n" );
+ else if (ch == '\r')
+ o.print( "\\r" );
+ else if (ch == '\t')
+ o.print( "\\t" );
+ else if (ch == '\"')
+ o.print( "\\\"" );
+ else
+ o.print( "<#" + ((int) ch) + ">" );
+ } else {
+ o.print( "<#" + codePoint + ">" );
+ }
+
+ i += Character.charCount(codePoint);
}
o.print( "\"" );
diff --git a/xmlbeans/src/store/org/apache/xmlbeans/impl/store/Locale.java b/xmlbeans/src/store/org/apache/xmlbeans/impl/store/Locale.java
index 531f8763e5..b5a1cc433f 100755
--- a/xmlbeans/src/store/org/apache/xmlbeans/impl/store/Locale.java
+++ b/xmlbeans/src/store/org/apache/xmlbeans/impl/store/Locale.java
@@ -1,4 +1,4 @@
-/* Copyright 2004 The Apache Software Foundation
+/* Copyright 2004-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.
@@ -25,7 +25,6 @@ import org.xml.sax.InputSource;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.ext.DeclHandler;
import org.xml.sax.SAXParseException;
-import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.SAXException;
import org.xml.sax.DTDHandler;
@@ -38,8 +37,6 @@ import java.lang.ref.Reference;
import java.lang.ref.PhantomReference;
import java.lang.ref.SoftReference;
-import java.lang.reflect.Method;
-
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
@@ -106,9 +103,6 @@ import org.apache.xmlbeans.impl.values.TypeStore;
import org.apache.xmlbeans.impl.values.TypeStoreUser;
import org.apache.xmlbeans.impl.values.TypeStoreUserFactory;
-import org.apache.xmlbeans.impl.piccolo.xml.Piccolo;
-import org.apache.xmlbeans.impl.piccolo.io.FileFormatException;
-
public final class Locale
implements DOMImplementation, SaajCallback, XmlLocale
{
@@ -3035,18 +3029,7 @@ public final class Locale
}
}
- private static SaxLoader getPiccoloSaxLoader()
- {
- SaxLoader piccoloLoader = (SaxLoader) SystemCache.get().getSaxLoader();
- if (piccoloLoader == null)
- {
- piccoloLoader = PiccoloSaxLoader.newInstance();
- SystemCache.get().setSaxLoader(piccoloLoader);
- }
- return piccoloLoader;
- }
-
- private static SaxLoader getSaxLoader(XmlOptions options)
+ private static SaxLoader getSaxLoader(XmlOptions options) throws XmlException
{
options = XmlOptions.maskNull(options);
@@ -3063,31 +3046,23 @@ public final class Locale
er = new DefaultEntityResolver();
}
- SaxLoader sl;
+ XMLReader xr = (XMLReader) options.get(
+ XmlOptions.LOAD_USE_XMLREADER);
- if (options.hasOption(XmlOptions.LOAD_USE_XMLREADER))
- {
- XMLReader xr = (XMLReader) options.get(
- XmlOptions.LOAD_USE_XMLREADER);
-
- if (xr == null)
- throw new IllegalArgumentException("XMLReader is null");
-
- sl = new XmlReaderSaxLoader(xr);
-
- // I've noticed that most XMLReaders don't like a null EntityResolver...
-
- if (er != null)
- xr.setEntityResolver(er);
+ if (xr == null) {
+ try {
+ xr = SAXHelper.newXMLReader();
+ } catch(Exception e) {
+ throw new XmlException("Problem creating XMLReader", e);
+ }
}
- else
- {
- sl = getPiccoloSaxLoader();
- // Piccolo doesnot mind a null entity resolver ...
+ SaxLoader sl = new XmlReaderSaxLoader(xr);
- sl.setEntityResolver(er);
- }
+ // I've noticed that most XMLReaders don't like a null EntityResolver...
+
+ if (er != null)
+ xr.setEntityResolver(er);
return sl;
}
@@ -3101,34 +3076,6 @@ public final class Locale
}
}
- private static class PiccoloSaxLoader
- extends SaxLoader
- {
- private PiccoloSaxLoader(Piccolo p)
- {
- super(p, p.getStartLocator());
-
- _piccolo = p;
- }
-
- static PiccoloSaxLoader newInstance()
- {
- return new PiccoloSaxLoader(new Piccolo());
- }
-
- void postLoad(Cur c)
- {
- XmlDocumentProperties props = getDocProps(c, true);
-
- props.setEncoding(_piccolo.getEncoding());
- props.setVersion(_piccolo.getVersion());
-
- super.postLoad(c);
- }
-
- private Piccolo _piccolo;
- }
-
private static abstract class SaxHandler
implements ContentHandler, LexicalHandler , DeclHandler, DTDHandler
{
@@ -3183,7 +3130,7 @@ public final class Locale
if (local.length() == 0)
local = qName;
- // Out current parser (Piccolo) does not error when a
+ // Out current parser does not error when a
// namespace is used and not defined. Check for these here
if (qName.indexOf(':') >= 0 && uri.length() == 0)
@@ -3473,12 +3420,6 @@ public final class Locale
return c;
}
- catch (FileFormatException e)
- {
- _context.abort();
-
- throw new XmlException(e.getMessage(), e);
- }
catch (XmlRuntimeException e)
{
_context.abort();
diff --git a/xmlbeans/src/store/org/apache/xmlbeans/impl/store/NullLogger.java b/xmlbeans/src/store/org/apache/xmlbeans/impl/store/NullLogger.java
new file mode 100644
index 0000000000..aca8d1d5ff
--- /dev/null
+++ b/xmlbeans/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.
+ */
+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/xmlbeans/src/store/org/apache/xmlbeans/impl/store/SAXHelper.java b/xmlbeans/src/store/org/apache/xmlbeans/impl/store/SAXHelper.java
new file mode 100644
index 0000000000..67fb3a0e9f
--- /dev/null
+++ b/xmlbeans/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/xmlbeans/src/store/org/apache/xmlbeans/impl/store/Saver.java b/xmlbeans/src/store/org/apache/xmlbeans/impl/store/Saver.java
index 1344aaacfc..c7832aa2fc 100755
--- a/xmlbeans/src/store/org/apache/xmlbeans/impl/store/Saver.java
+++ b/xmlbeans/src/store/org/apache/xmlbeans/impl/store/Saver.java
@@ -275,7 +275,23 @@ abstract class Saver
end.moveToCur( c );
end.toEnd();
}
-
+
+ /**
+ * Test if a character is valid in xml character content. See
+ * http://www.w3.org/TR/REC-xml#NT-Char
+ */
+ static boolean isBadChar ( char ch )
+ {
+ return ! (
+ Character.isHighSurrogate(ch) ||
+ Character.isLowSurrogate(ch) ||
+ (ch >= 0x20 && ch <= 0xD7FF ) ||
+ (ch >= 0xE000 && ch <= 0xFFFD) ||
+ (ch >= 0x10000 && ch <= 0x10FFFF) ||
+ (ch == 0x9) || (ch == 0xA) || (ch == 0xD)
+ );
+ }
+
protected boolean saveNamespacesFirst ( )
{
return _saveNamespacesFirst;
@@ -1387,7 +1403,7 @@ abstract class Saver
if (++i == _buf.length)
i = 0;
- for ( int cch = _lastEmitCch ; cch > 0 ; cch-- )
+ for ( int cch = _lastEmitCch - 2 ; cch > 0 ; cch-- )
{
char ch = _buf[ i ];
@@ -1551,21 +1567,6 @@ abstract class Saver
}
}
- /**
- * Test if a character is valid in xml character content. See
- * http://www.w3.org/TR/REC-xml#NT-Char
- */
-
- private boolean isBadChar ( char ch )
- {
- return ! (
- (ch >= 0x20 && ch <= 0xD7FF ) ||
- (ch >= 0xE000 && ch <= 0xFFFD) ||
- (ch >= 0x10000 && ch <= 0x10FFFF) ||
- (ch == 0x9) || (ch == 0xA) || (ch == 0xD)
- );
- }
-
/**
* Test if a character is to be replaced with an escaped value
*/
@@ -2190,20 +2191,6 @@ abstract class Saver
}
}
- /**
- * Test if a character is valid in xml character content. See
- * http://www.w3.org/TR/REC-xml#NT-Char
- */
- private boolean isBadChar ( char ch )
- {
- return ! (
- (ch >= 0x20 && ch <= 0xD7FF ) ||
- (ch >= 0xE000 && ch <= 0xFFFD) ||
- (ch >= 0x10000 && ch <= 0x10FFFF) ||
- (ch == 0x9) || (ch == 0xA) || (ch == 0xD)
- );
- }
-
private void emitLiteral ( String literal )
{
// TODO: systemId production http://www.w3.org/TR/REC-xml/#NT-SystemLiteral
diff --git a/xmlbeans/src/store/org/apache/xmlbeans/impl/store/XBLogFactory.java b/xmlbeans/src/store/org/apache/xmlbeans/impl/store/XBLogFactory.java
new file mode 100644
index 0000000000..f31d4db7bc
--- /dev/null
+++ b/xmlbeans/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 _loggers = new HashMap();
+
+ /**
+ * 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/xmlbeans/src/store/org/apache/xmlbeans/impl/store/XBLogger.java b/xmlbeans/src/store/org/apache/xmlbeans/impl/store/XBLogger.java
new file mode 100644
index 0000000000..fa605112f0
--- /dev/null
+++ b/xmlbeans/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.
+ */
+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:
+ *
+ * if (logger.check(XBLogger.INFO)) {
+ * logger.log(XBLogger.INFO, "Avoid concatenating " + " strings and evaluating " + functions());
+ * }
+ *
+ *
+ * @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; iQName class represents the value of a qualified name
- * as specified in XML
- * Schema Part2: Datatypes specification.
- *
- * The value of a QName contains a namespaceURI, a localPart and a prefix.
- * The localPart provides the local part of the qualified name. The
- * namespaceURI is a URI reference identifying the namespace.
- *
- * @version 1.1
- */
-public class QName implements Serializable {
-
- private static final long serialVersionUID = -9120448754896609940L;
-
- /** comment/shared empty string */
- private static final String emptyString = "".intern();
-
- /** Field namespaceURI */
- private String namespaceURI;
-
- /** Field localPart */
- private String localPart;
-
- /** Field prefix */
- private String prefix;
-
- /**
- * Constructor for the QName.
- *
- * @param localPart Local part of the QName
- */
- public QName(String localPart) {
- this(emptyString, localPart, emptyString);
- }
-
- /**
- * Constructor for the QName.
- *
- * @param namespaceURI Namespace URI for the QName
- * @param localPart Local part of the QName.
- */
- public QName(String namespaceURI, String localPart) {
- this(namespaceURI, localPart, emptyString);
- }
-
- /**
- * Constructor for the QName.
- *
- * @param namespaceURI Namespace URI for the QName
- * @param localPart Local part of the QName.
- * @param prefix Prefix of the QName.
- */
- public QName(String namespaceURI, String localPart, String prefix) {
- this.namespaceURI = (namespaceURI == null)
- ? emptyString
- : namespaceURI.intern();
- if (localPart == null) {
- throw new IllegalArgumentException("invalid QName local part");
- } else {
- this.localPart = localPart.intern();
- }
-
- if (prefix == null) {
- throw new IllegalArgumentException("invalid QName prefix");
- } else {
- this.prefix = prefix.intern();
- }
- }
-
- /**
- * Gets the Namespace URI for this QName
- *
- * @return Namespace URI
- */
- public String getNamespaceURI() {
- return namespaceURI;
- }
-
- /**
- * Gets the Local part for this QName
- *
- * @return Local part
- */
- public String getLocalPart() {
- return localPart;
- }
-
- /**
- * Gets the Prefix for this QName
- *
- * @return Prefix
- */
- public String getPrefix() {
- return prefix;
- }
-
- /**
- * Returns a string representation of this QName
- *
- * @return a string representation of the QName
- */
- public String toString() {
-
- return ((namespaceURI == emptyString)
- ? localPart
- : '{' + namespaceURI + '}' + localPart);
- }
-
- /**
- * Tests this QName for equality with another object.
- *
- * If the given object is not a QName or is null then this method
- * returns false.
- *
- * For two QNames to be considered equal requires that both
- * localPart and namespaceURI must be equal. This method uses
- * String.equals
to check equality of localPart
- * and namespaceURI. Any class that extends QName is required
- * to satisfy this equality contract.
- *
- * This method satisfies the general contract of the Object.equals
method.
- *
- * @param obj the reference object with which to compare
- *
- * @return true
if the given object is identical to this
- * QName: false
otherwise.
- */
- public final boolean equals(Object obj) {
-
- if (obj == this) {
- return true;
- }
-
- if (!(obj instanceof QName)) {
- return false;
- }
-
- if ((namespaceURI == ((QName) obj).namespaceURI)
- && (localPart == ((QName) obj).localPart)) {
- return true;
- }
-
- return false;
- }
-
- /**
- * Returns a QName holding the value of the specified String.
- *
- * The string must be in the form returned by the QName.toString()
- * method, i.e. "{namespaceURI}localPart", with the "{namespaceURI}"
- * part being optional.
- *
- * This method doesn't do a full validation of the resulting QName.
- * In particular, it doesn't check that the resulting namespace URI
- * is a legal URI (per RFC 2396 and RFC 2732), nor that the resulting
- * local part is a legal NCName per the XML Namespaces specification.
- *
- * @param s the string to be parsed
- * @throws java.lang.IllegalArgumentException If the specified String cannot be parsed as a QName
- * @return QName corresponding to the given String
- */
- public static QName valueOf(String s) {
-
- if ((s == null) || s.equals("")) {
- throw new IllegalArgumentException("invalid QName literal");
- }
-
- if (s.charAt(0) == '{') {
- int i = s.indexOf('}');
-
- if (i == -1) {
- throw new IllegalArgumentException("invalid QName literal");
- }
-
- if (i == s.length() - 1) {
- throw new IllegalArgumentException("invalid QName literal");
- } else {
- return new QName(s.substring(1, i), s.substring(i + 1));
- }
- } else {
- return new QName(s);
- }
- }
-
- /**
- * Returns a hash code value for this QName object. The hash code
- * is based on both the localPart and namespaceURI parts of the
- * QName. This method satisfies the general contract of the
- * Object.hashCode
method.
- *
- * @return a hash code value for this Qname object
- */
- public final int hashCode() {
- return namespaceURI.hashCode() ^ localPart.hashCode();
- }
-
- /**
- * Ensure that deserialization properly interns the results.
- * @param in the ObjectInputStream to be read
- */
- private void readObject(ObjectInputStream in) throws
- IOException, ClassNotFoundException {
- in.defaultReadObject();
-
- namespaceURI = namespaceURI.intern();
- localPart = localPart.intern();
- prefix = prefix.intern();
- }
-}
diff --git a/xmlbeans/test/src/xmlcursor/checkin/StoreTests.java b/xmlbeans/test/src/xmlcursor/checkin/StoreTests.java
index ac0ec29465..80ab820ba3 100755
--- a/xmlbeans/test/src/xmlcursor/checkin/StoreTests.java
+++ b/xmlbeans/test/src/xmlcursor/checkin/StoreTests.java
@@ -1112,7 +1112,7 @@ public class StoreTests extends TestCase
throws Exception
{
XmlCursor c = XmlObject.Factory.parse( xml ).newCursor();
- Assert.assertTrue( c.xmlText().equals( xml ) );
+ Assert.assertEquals( xml, c.xmlText() );
}
private void doSaveTest ( String xml )
@@ -1121,6 +1121,16 @@ public class StoreTests extends TestCase
doSaverTest( xml );
}
+ public void testCDATA() throws Exception
+ {
+ // https://issues.apache.org/jira/browse/XMLBEANS-404
+ String xml = "Unable to render embedded object: >>>>>>><<<<<<<<<<<]]>";
+ String expected = ">>>>>>><<<<<<<<<<<]]>";
+ XmlOptions options = new XmlOptions().setSaveCDataLengthThreshold(0);
+ XmlCursor c = XmlObject.Factory.parse(xml, options).newCursor();
+ Assert.assertEquals( expected, c.xmlText(options) );
+ }
+
public void testSaving ( )
throws Exception
{
diff --git a/xmlbeans/test/src/xmlobject/checkin/AssortedTests.java b/xmlbeans/test/src/xmlobject/checkin/AssortedTests.java
index a6364a81f8..ce4b235219 100755
--- a/xmlbeans/test/src/xmlobject/checkin/AssortedTests.java
+++ b/xmlbeans/test/src/xmlobject/checkin/AssortedTests.java
@@ -40,7 +40,6 @@ public class AssortedTests extends TestCase
// bug 27489
public static void testSaverCharEscaping() throws XmlException
{
- String newLine = System.getProperty( "line.separator" );
XmlObject xdoc = XmlObject.Factory.parse("something");
XmlCursor cur = xdoc.newCursor();
cur.toFirstChild();
@@ -48,9 +47,14 @@ public class AssortedTests extends TestCase
cur.setTextValue("");
Assert.assertEquals("<something or other:\u03C0\uD7FF>", xdoc.toString());
- // invalid chars - control chars, unicode surrogates, FFFF/FFFE, etc
- cur.setTextValue("");
- Assert.assertEquals("<something?or?other:\u0045?????\u03C0\uD7FF?>", xdoc.toString());
+ // invalid chars - control chars, FFFF/FFFE, etc
+ cur.setTextValue("");
+ Assert.assertEquals("<something?or?other:\u0045?>", xdoc.toString());
+
+ String greekChars = "\uD835\uDF4A\uD835\uDF4B\uD835\uDF4C\uD835\uDF4D\uD835\uDF4E\uD835\uDF4F\uD835\uDF50\uD835"
+ + "\uDF51\uD835\uDF52\uD835\uDF53\uD835\uDF54\uD835\uDF55";
+ cur.setTextValue(greekChars);
+ Assert.assertEquals("" + greekChars + "", xdoc.toString());
}
// bug 26140/26104
diff --git a/xmlbeans/test/src/xmlobject/checkin/CDataTest.java b/xmlbeans/test/src/xmlobject/checkin/CDataTest.java
index 1b64a5283e..791e212111 100644
--- a/xmlbeans/test/src/xmlobject/checkin/CDataTest.java
+++ b/xmlbeans/test/src/xmlobject/checkin/CDataTest.java
@@ -53,8 +53,8 @@ public class CDataTest
throws Exception
{
String xmlText = "";
-
- checkCData(xmlText, xmlText, xmlText);
+ String resultText = "cdata text";
+ checkCData(xmlText, resultText, resultText);
}
public void testCData2()
@@ -64,10 +64,10 @@ public class CDataTest
" regular text" + NL +
"";
String expected1 = "\n" +
- "\n" +
+ "cdata text regular text\n" +
"";
String expected2 = "" + NL +
- " " + NL +
+ " cdata text regular text" + NL +
"";
checkCData(xmlText, expected1, expected2);
@@ -89,6 +89,23 @@ public class CDataTest
checkCData(xmlText, expected1, expected2);
}
+ // https://issues.apache.org/jira/browse/XMLBEANS-404
+ public void testXmlBeans404()
+ throws Exception
+ {
+ String xmlText = "\n" +
+ "text \n" +
+ "";
+ String expected1 = "\n" +
+ "text cdata text]]\n" +
+ "";
+ String expected2 = "" + NL +
+ " text cdata text]]" + NL +
+ "";
+
+ checkCData(xmlText, expected1, expected2);
+ }
+
private void checkCData(String xmlText, String expected1, String expected2)
throws XmlException
{